From af3c65088e0ff0294effded83cdbf18e80c05043 Mon Sep 17 00:00:00 2001 From: The Agent Substrate Seed Team Date: Wed, 13 May 2026 12:02:38 -0700 Subject: [PATCH] Initial commit of Agent Substrate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the initial release of the Agent Substrate. Agent substrate is a system built on top of Kubernetes which manages agent-like workloads to achieve higher scale and efficiency than Kubernetes alone can offer, with lower latency. It builds on top of Kubernetes features like Pods and Pod autoscaling, but takes the Kubernetes control-plane out of the critical path to achieve lower latency. It can run on any Kubernetes cluster and does not inhibit “regular” use of Kubernetes in any way. Kubernetes provides the infrastructure provisioning and management for all types of workloads, while Agent Substrate provides agent-specific scheduling and control. At its core, Agent Substrate maps a larger set of “actors” (applications such as agents) onto a smaller set of ready “workers” (Kubernetes Pods), relying on the fact that agent-like applications tend to be idle most of the time to achieve heavy multiplexing. It provides functionality to manage an actor’s lifecycle (e.g. create/destroy, suspend/resume), to assign actors to workers in real time, and to route incoming traffic to them. Agent Substrate is intended to be a low-opinion system. The workloads it manages don't have to be literal AI agents, but those are the best example of the kind of applications it is designed for. It is not an SDK for building agents, but rather a system for running them at scale. Agent Substrate is currently in VERY early development. It is not ready for production use, and the APIs are almost guaranteed to change. We are not making any guarantees about backward compatibility at this stage, and everything in this project may be changed. Co-authored-by: Alex Bulankou Co-authored-by: Benjamin Elder Co-authored-by: Bowei Du Co-authored-by: Dmitry Berkovich Co-authored-by: Fabricio Voznika Co-authored-by: Francisco Cabrera Co-authored-by: Haven Xia Co-authored-by: Julian Gutierrez Oschmann Co-authored-by: Kevin Steuer Co-authored-by: Max Smythe Co-authored-by: Maya Wang Co-authored-by: Michael Taufen Co-authored-by: Shruti Nair Co-authored-by: Taahir Ahmed Co-authored-by: Tim Hockin Co-authored-by: Zoe Zhao --- .agents/skills/agents-md/SKILL.md | 71 + .github/ISSUE_TEMPLATE/bug_report.md | 22 + .github/PULL_REQUEST_TEMPLATE.md | 6 + .github/workflows/pr-workflow.yaml | 52 + .gitignore | 15 + .ko.yaml | 19 + AGENTS.md | 49 + COLLABORATING.md | 88 + CONTRIBUTING.md | 67 + LICENSE | 206 +++ LICENSES/cel.dev/expr/LICENSE | 202 +++ LICENSES/cloud.google.com/go/auth/LICENSE | 202 +++ .../go/auth/oauth2adapt/LICENSE | 202 +++ .../go/compute/metadata/LICENSE | 202 +++ .../cloud.google.com/go/container/LICENSE | 202 +++ LICENSES/cloud.google.com/go/iam/LICENSE | 202 +++ LICENSES/cloud.google.com/go/internal/LICENSE | 202 +++ .../cloud.google.com/go/longrunning/LICENSE | 202 +++ .../cloud.google.com/go/monitoring/LICENSE | 202 +++ .../go/resourcemanager/LICENSE | 202 +++ .../cloud.google.com/go/serviceusage/LICENSE | 202 +++ LICENSES/cloud.google.com/go/storage/LICENSE | 202 +++ .../detectors/gcp/LICENSE | 202 +++ .../exporter/metric/LICENSE | 202 +++ .../internal/resourcemapping/LICENSE | 202 +++ .../github.com/alicebob/miniredis/v2/LICENSE | 21 + .../alicebob/miniredis/v2/fpconv/LICENSE.txt | 26 + .../alicebob/miniredis/v2/geohash/LICENSE | 22 + .../alicebob/miniredis/v2/gopher-json/LICENSE | 24 + .../alicebob/miniredis/v2/hyperloglog/LICENSE | 21 + .../alicebob/miniredis/v2/metro/LICENSE | 24 + .../github.com/aws/aws-sdk-go-v2/LICENSE.txt | 202 +++ .../github.com/aws/aws-sdk-go-v2/NOTICE.txt | 3 + .../aws/protocol/eventstream/LICENSE.txt | 202 +++ .../aws/aws-sdk-go-v2/config/LICENSE.txt | 202 +++ .../aws/aws-sdk-go-v2/credentials/LICENSE.txt | 202 +++ .../feature/ec2/imds/LICENSE.txt | 202 +++ .../internal/configsources/LICENSE.txt | 202 +++ .../internal/endpoints/v2/LICENSE.txt | 202 +++ .../internal/sync/singleflight/LICENSE | 28 + .../aws-sdk-go-v2/internal/v4a/LICENSE.txt | 202 +++ .../internal/accept-encoding/LICENSE.txt | 202 +++ .../service/internal/checksum/LICENSE.txt | 202 +++ .../internal/presigned-url/LICENSE.txt | 202 +++ .../service/internal/s3shared/LICENSE.txt | 202 +++ .../aws/aws-sdk-go-v2/service/s3/LICENSE.txt | 202 +++ .../aws-sdk-go-v2/service/signin/LICENSE.txt | 202 +++ .../aws/aws-sdk-go-v2/service/sso/LICENSE.txt | 202 +++ .../aws-sdk-go-v2/service/ssooidc/LICENSE.txt | 202 +++ .../aws/aws-sdk-go-v2/service/sts/LICENSE.txt | 202 +++ LICENSES/github.com/aws/smithy-go/LICENSE | 175 ++ LICENSES/github.com/aws/smithy-go/NOTICE | 1 + .../internal/sync/singleflight/LICENSE | 28 + .../github.com/beorn7/perks/quantile/LICENSE | 20 + .../github.com/cenkalti/backoff/v5/LICENSE | 20 + .../github.com/cespare/xxhash/v2/LICENSE.txt | 22 + LICENSES/github.com/cncf/xds/go/LICENSE | 201 +++ .../stargz-snapshotter/estargz/LICENSE | 202 +++ .../github.com/davecgh/go-spew/spew/LICENSE | 15 + .../github.com/dgryski/go-rendezvous/LICENSE | 21 + .../github.com/docker/cli/cli/config/LICENSE | 191 +++ .../github.com/docker/cli/cli/config/NOTICE | 19 + .../docker/docker-credential-helpers/LICENSE | 20 + .../github.com/emicklei/go-restful/v3/LICENSE | 22 + .../envoyproxy/go-control-plane/envoy/LICENSE | 201 +++ .../envoyproxy/go-control-plane/pkg/LICENSE | 201 +++ .../ratelimit/service/ratelimit/v3/LICENSE | 201 +++ .../protoc-gen-validate/validate/LICENSE | 202 +++ .../github.com/evanphx/json-patch/v5/LICENSE | 25 + .../github.com/felixge/httpsnoop/LICENSE.txt | 19 + LICENSES/github.com/fsnotify/fsnotify/LICENSE | 25 + LICENSES/github.com/fxamacker/cbor/v2/LICENSE | 21 + .../github.com/go-jose/go-jose/v4/LICENSE | 202 +++ .../go-jose/go-jose/v4/json/LICENSE | 27 + LICENSES/github.com/go-logr/logr/LICENSE | 201 +++ LICENSES/github.com/go-logr/stdr/LICENSE | 201 +++ LICENSES/github.com/go-logr/zapr/LICENSE | 201 +++ .../github.com/go-openapi/jsonpointer/LICENSE | 201 +++ .../github.com/go-openapi/jsonpointer/NOTICE | 39 + .../go-openapi/jsonreference/LICENSE | 202 +++ .../go-openapi/jsonreference/NOTICE | 39 + LICENSES/github.com/go-openapi/swag/LICENSE | 202 +++ .../go-openapi/swag/cmdutils/LICENSE | 202 +++ .../github.com/go-openapi/swag/conv/LICENSE | 202 +++ .../go-openapi/swag/fileutils/LICENSE | 202 +++ .../go-openapi/swag/jsonname/LICENSE | 202 +++ .../go-openapi/swag/jsonutils/LICENSE | 202 +++ .../go-openapi/swag/loading/LICENSE | 202 +++ .../go-openapi/swag/mangling/LICENSE | 202 +++ .../go-openapi/swag/netutils/LICENSE | 202 +++ .../go-openapi/swag/stringutils/LICENSE | 202 +++ .../go-openapi/swag/typeutils/LICENSE | 202 +++ .../go-openapi/swag/yamlutils/LICENSE | 202 +++ LICENSES/github.com/google/btree/LICENSE | 202 +++ .../github.com/google/gnostic-models/LICENSE | 203 +++ LICENSES/github.com/google/go-cmp/cmp/LICENSE | 27 + .../google/go-containerregistry/LICENSE | 202 +++ LICENSES/github.com/google/s2a-go/LICENSE.md | 202 +++ LICENSES/github.com/google/uuid/LICENSE | 27 + .../client/LICENSE | 202 +++ .../github.com/googleapis/gax-go/v2/LICENSE | 27 + LICENSES/github.com/gorilla/websocket/LICENSE | 22 + .../grpc-ecosystem/grpc-gateway/v2/LICENSE | 27 + .../github.com/hashicorp/go-reap/.gitignore | 24 + LICENSES/github.com/hashicorp/go-reap/LICENSE | 365 +++++ .../github.com/hashicorp/go-reap/README.md | 46 + LICENSES/github.com/hashicorp/go-reap/reap.go | 8 + .../github.com/hashicorp/go-reap/reap_stub.go | 17 + .../hashicorp/go-reap/reap_stub_test.go | 27 + .../github.com/hashicorp/go-reap/reap_unix.go | 96 ++ .../hashicorp/go-reap/reap_unix_test.go | 129 ++ LICENSES/github.com/json-iterator/go/LICENSE | 21 + .../github.com/klauspost/compress/LICENSE | 304 ++++ .../compress/internal/snapref/LICENSE | 27 + .../compress/zstd/internal/xxhash/LICENSE.txt | 22 + .../github.com/mitchellh/go-homedir/LICENSE | 21 + LICENSES/github.com/moby/spdystream/LICENSE | 202 +++ LICENSES/github.com/moby/spdystream/NOTICE | 17 + .../github.com/moby/spdystream/spdy/LICENSE | 27 + .../github.com/modern-go/concurrent/LICENSE | 201 +++ .../github.com/modern-go/reflect2/LICENSE | 201 +++ LICENSES/github.com/munnerz/goautoneg/LICENSE | 31 + .../opencontainers/go-digest/LICENSE | 192 +++ .../image-spec/specs-go/LICENSE | 191 +++ .../runtime-spec/specs-go/LICENSE | 191 +++ .../pmezard/go-difflib/difflib/LICENSE | 27 + .../github.com/golang/gddo/httputil/LICENSE | 27 + .../client_golang/prometheus/LICENSE | 201 +++ .../client_golang/prometheus/NOTICE | 18 + .../prometheus/client_model/go/LICENSE | 201 +++ .../prometheus/client_model/go/NOTICE | 5 + LICENSES/github.com/prometheus/common/LICENSE | 201 +++ LICENSES/github.com/prometheus/common/NOTICE | 5 + .../prometheus/otlptranslator/LICENSE | 201 +++ LICENSES/github.com/prometheus/procfs/LICENSE | 201 +++ LICENSES/github.com/prometheus/procfs/NOTICE | 7 + LICENSES/github.com/redis/go-redis/v9/LICENSE | 25 + LICENSES/github.com/sirupsen/logrus/LICENSE | 21 + LICENSES/github.com/spf13/cobra/LICENSE.txt | 174 ++ LICENSES/github.com/spf13/pflag/LICENSE | 28 + .../github.com/spiffe/go-spiffe/v2/LICENSE | 201 +++ .../vbatts/tar-split/archive/tar/LICENSE | 28 + .../github.com/vishvananda/netlink/LICENSE | 192 +++ LICENSES/github.com/vishvananda/netns/LICENSE | 192 +++ LICENSES/github.com/x448/float16/LICENSE | 22 + LICENSES/github.com/yuin/gopher-lua/LICENSE | 21 + LICENSES/go.opentelemetry.io/auto/sdk/LICENSE | 201 +++ .../contrib/detectors/gcp/LICENSE | 231 +++ .../google.golang.org/grpc/otelgrpc/LICENSE | 231 +++ .../instrumentation/net/http/otelhttp/LICENSE | 231 +++ LICENSES/go.opentelemetry.io/otel/LICENSE | 231 +++ .../otlp/otlpmetric/otlpmetricgrpc/LICENSE | 231 +++ .../otel/exporters/otlp/otlptrace/LICENSE | 231 +++ .../otlp/otlptrace/otlptracegrpc/LICENSE | 231 +++ .../otel/exporters/prometheus/LICENSE | 231 +++ .../go.opentelemetry.io/otel/metric/LICENSE | 231 +++ LICENSES/go.opentelemetry.io/otel/sdk/LICENSE | 231 +++ .../otel/sdk/metric/LICENSE | 231 +++ .../go.opentelemetry.io/otel/trace/LICENSE | 231 +++ .../go.opentelemetry.io/proto/otlp/LICENSE | 201 +++ LICENSES/go.uber.org/atomic/LICENSE.txt | 19 + LICENSES/go.uber.org/multierr/LICENSE.txt | 19 + LICENSES/go.uber.org/zap/LICENSE | 19 + LICENSES/go.yaml.in/yaml/v2/LICENSE | 201 +++ LICENSES/go.yaml.in/yaml/v2/NOTICE | 13 + LICENSES/go.yaml.in/yaml/v3/LICENSE | 50 + LICENSES/go.yaml.in/yaml/v3/NOTICE | 13 + LICENSES/golang.org/x/crypto/LICENSE | 27 + LICENSES/golang.org/x/net/LICENSE | 27 + LICENSES/golang.org/x/oauth2/LICENSE | 27 + LICENSES/golang.org/x/sync/LICENSE | 27 + LICENSES/golang.org/x/sys/LICENSE | 27 + LICENSES/golang.org/x/sys/unix/LICENSE | 27 + LICENSES/golang.org/x/term/LICENSE | 27 + LICENSES/golang.org/x/text/LICENSE | 27 + LICENSES/golang.org/x/time/rate/LICENSE | 27 + LICENSES/gomodules.xyz/jsonpatch/v2/LICENSE | 202 +++ LICENSES/google.golang.org/api/LICENSE | 27 + .../internal/third_party/uritemplates/LICENSE | 27 + .../genproto/googleapis/api/LICENSE | 202 +++ .../genproto/googleapis/rpc/LICENSE | 202 +++ .../genproto/googleapis/type/LICENSE | 202 +++ LICENSES/google.golang.org/grpc/LICENSE | 202 +++ LICENSES/google.golang.org/grpc/NOTICE.txt | 13 + LICENSES/google.golang.org/protobuf/LICENSE | 27 + .../gopkg.in/evanphx/json-patch.v4/LICENSE | 25 + LICENSES/gopkg.in/inf.v0/LICENSE | 28 + LICENSES/k8s.io/api/LICENSE | 202 +++ .../apiextensions-apiserver/pkg/LICENSE | 202 +++ LICENSES/k8s.io/apimachinery/pkg/LICENSE | 202 +++ .../third_party/forked/golang/LICENSE | 27 + LICENSES/k8s.io/client-go/LICENSE | 202 +++ LICENSES/k8s.io/klog/v2/LICENSE | 191 +++ LICENSES/k8s.io/kube-openapi/pkg/LICENSE | 202 +++ .../go-json-experiment/json/LICENSE | 27 + .../kube-openapi/pkg/validation/spec/LICENSE | 202 +++ LICENSES/k8s.io/streaming/pkg/LICENSE | 202 +++ LICENSES/k8s.io/utils/LICENSE | 202 +++ .../third_party/forked/golang/LICENSE | 27 + .../sigs.k8s.io/controller-runtime/LICENSE | 201 +++ LICENSES/sigs.k8s.io/json/LICENSE | 238 +++ LICENSES/sigs.k8s.io/randfill/LICENSE | 202 +++ LICENSES/sigs.k8s.io/randfill/NOTICE | 24 + .../structured-merge-diff/v6/LICENSE | 201 +++ LICENSES/sigs.k8s.io/yaml/LICENSE | 306 ++++ Makefile | 79 + README.md | 188 +++ api/v1alpha1/actortemplate_types.go | 176 ++ api/v1alpha1/actortemplate_types_test.go | 51 + api/v1alpha1/gen.go | 20 + api/v1alpha1/groupversion_info.go | 41 + api/v1alpha1/workerpool_types.go | 67 + api/v1alpha1/zz_generated.deepcopy.go | 344 ++++ benchmarking/README.md | 86 + benchmarking/locust/Dockerfile | 35 + benchmarking/locust/__init__.py | 13 + benchmarking/locust/build_and_push.sh | 41 + benchmarking/locust/common/__init__.py | 13 + benchmarking/locust/common/ateapi_pb2.py | 99 ++ benchmarking/locust/common/ateapi_pb2_grpc.py | 592 +++++++ benchmarking/locust/common/metrics.py | 95 ++ benchmarking/locust/common/trace.py | 93 ++ benchmarking/locust/common/wait_time.py | 51 + benchmarking/locust/deploy_locust.sh | 67 + benchmarking/locust/generate_protos.sh | 63 + benchmarking/locust/manifests/all.yaml | 91 ++ benchmarking/locust/manifests/ate-api.yaml | 71 + .../locust/manifests/counter-demo.yaml | 61 + benchmarking/locust/manifests/workloads.yaml | 73 + benchmarking/locust/requirements.txt | 25 + benchmarking/locust/shapes/__init__.py | 13 + benchmarking/locust/shapes/burst_shape.py | 40 + benchmarking/locust/tests/__init__.py | 13 + benchmarking/locust/tests/ate_api.py | 189 +++ benchmarking/locust/tests/counter_demo.py | 171 ++ benchmarking/locust/tests/kernelmem.py | 161 ++ benchmarking/locust/tests/sleep.py | 161 ++ benchmarking/locust/tests/usermem.py | 161 ++ benchmarking/monitoring.yaml | 573 +++++++ benchmarking/workloads/deploy.sh | 92 ++ .../manifests/full_workloads.yaml.tmpl | 137 ++ .../workloads/manifests/workloads.yaml.tmpl | 63 + cmd/kubectl-ate/README.md | 112 ++ cmd/kubectl-ate/cmd/admin.go | 28 + .../cmd/admin_debug_redis_flush.go | 48 + cmd/kubectl-ate/cmd/admin_make_ca_pool.go | 88 + cmd/kubectl-ate/cmd/admin_make_jwt_pool.go | 86 + cmd/kubectl-ate/cmd/create.go | 28 + cmd/kubectl-ate/cmd/create_actor.go | 64 + cmd/kubectl-ate/cmd/delete.go | 28 + cmd/kubectl-ate/cmd/delete_actor.go | 52 + cmd/kubectl-ate/cmd/get.go | 28 + cmd/kubectl-ate/cmd/get_actors.go | 60 + cmd/kubectl-ate/cmd/get_workers.go | 48 + cmd/kubectl-ate/cmd/logs.go | 28 + cmd/kubectl-ate/cmd/logs_actors.go | 151 ++ cmd/kubectl-ate/cmd/logs_actors_test.go | 105 ++ cmd/kubectl-ate/cmd/resume.go | 28 + cmd/kubectl-ate/cmd/resume_actor.go | 55 + cmd/kubectl-ate/cmd/root.go | 58 + cmd/kubectl-ate/cmd/suspend.go | 28 + cmd/kubectl-ate/cmd/suspend_actor.go | 51 + cmd/kubectl-ate/main.go | 23 + cmd/kubectl-ate/pkg/client/builder.go | 280 ++++ cmd/kubectl-ate/pkg/printer/printer.go | 137 ++ cmd/kubectl-ate/pkg/printer/printer_test.go | 167 ++ cmd/servers/ateapi/ateapi.go | 377 +++++ cmd/servers/ateapi/controlapi/create_actor.go | 82 + cmd/servers/ateapi/controlapi/debug_clear.go | 36 + cmd/servers/ateapi/controlapi/delete_actor.go | 62 + cmd/servers/ateapi/controlapi/dialer.go | 99 ++ .../ateapi/controlapi/functional_test.go | 1318 +++++++++++++++ cmd/servers/ateapi/controlapi/get_actor.go | 48 + cmd/servers/ateapi/controlapi/informer.go | 75 + cmd/servers/ateapi/controlapi/list_actors.go | 39 + cmd/servers/ateapi/controlapi/list_workers.go | 40 + cmd/servers/ateapi/controlapi/resume_actor.go | 51 + cmd/servers/ateapi/controlapi/service.go | 74 + cmd/servers/ateapi/controlapi/service_test.go | 90 + .../ateapi/controlapi/suspend_actor.go | 51 + cmd/servers/ateapi/controlapi/syncer.go | 141 ++ cmd/servers/ateapi/controlapi/syncer_test.go | 156 ++ cmd/servers/ateapi/controlapi/workflow.go | 212 +++ .../ateapi/controlapi/workflow_resume.go | 295 ++++ .../ateapi/controlapi/workflow_suspend.go | 240 +++ .../ateapi/sessionidentity/sessionidentity.go | 222 +++ cmd/servers/ateapi/store/ateredis/ateredis.go | 454 ++++++ .../ateapi/store/ateredis/ateredis_test.go | 723 ++++++++ cmd/servers/ateapi/store/store.go | 86 + .../ateapi/store/storetest/storetest.go | 47 + cmd/servers/atecontroller/main.go | 107 ++ cmd/servers/atelet/atelet.go | 796 +++++++++ cmd/servers/atelet/oci.go | 281 ++++ cmd/servers/atenet/app/dns/cmd.go | 106 ++ cmd/servers/atenet/app/root.go | 42 + cmd/servers/atenet/app/router/atstore.go | 55 + cmd/servers/atenet/app/router/atstore_file.go | 130 ++ cmd/servers/atenet/app/router/atstore_test.go | 143 ++ cmd/servers/atenet/app/router/controller.go | 110 ++ cmd/servers/atenet/app/router/dashboard.html | 458 ++++++ cmd/servers/atenet/app/router/envoyrunner.go | 258 +++ cmd/servers/atenet/app/router/extproc.go | 162 ++ cmd/servers/atenet/app/router/extproc_in.go | 81 + .../atenet/app/router/extproc_in_test.go | 195 +++ cmd/servers/atenet/app/router/extproc_out.go | 67 + cmd/servers/atenet/app/router/extproc_test.go | 155 ++ cmd/servers/atenet/app/router/health.go | 214 +++ cmd/servers/atenet/app/router/readme.md | 26 + cmd/servers/atenet/app/router/resumer.go | 93 ++ cmd/servers/atenet/app/router/resumer_test.go | 170 ++ cmd/servers/atenet/app/router/router.go | 334 ++++ cmd/servers/atenet/app/router/status.go | 274 ++++ cmd/servers/atenet/app/router/status_test.go | 142 ++ cmd/servers/atenet/app/router/xds.go | 483 ++++++ cmd/servers/atenet/app/router/xds_test.go | 212 +++ cmd/servers/atenet/atenet-diagram.png | Bin 0 -> 75853 bytes cmd/servers/atenet/main.go | 21 + cmd/servers/atenet/readme.md | 42 + cmd/servers/ateom-gvisor/ateom-gvisor.go | 585 +++++++ cmd/servers/ateom-gvisor/logger.go | 141 ++ cmd/servers/ateom-gvisor/logger_test.go | 99 ++ cmd/servers/ateom-gvisor/runsc.go | 234 +++ cmd/servers/ateom-gvisor/stopwatch.go | 64 + .../podcertcontroller/podcertcontroller.go | 149 ++ cmd/setup/cmd/api.go | 60 + cmd/setup/cmd/bucket.go | 139 ++ cmd/setup/cmd/cluster.go | 233 +++ cmd/setup/cmd/common.go | 78 + cmd/setup/cmd/iam.go | 131 ++ cmd/setup/cmd/root.go | 101 ++ cmd/setup/main.go | 29 + code-of-conduct.md | 95 ++ demos/agent-secret/README.md | 78 + demos/agent-secret/main.go | 138 ++ demos/claude-code-multiplex/README.md | 128 ++ demos/claude-code-multiplex/ui/index.html | 424 +++++ demos/claude-code-multiplex/ui/server.go | 542 ++++++ .../claude-code-multiplex/workload/Dockerfile | 29 + demos/claude-code-multiplex/workload/run.sh | 49 + demos/counter/.gitignore | 2 + demos/counter/README.md | 87 + demos/counter/counter.go | 143 ++ demos/sandbox/.gitignore | 3 + demos/sandbox/README.md | 101 ++ demos/sandbox/client/main.go | 201 +++ demos/sandbox/main.go | 118 ++ docs/api-guide.md | 171 ++ docs/architecture.md | 401 +++++ docs/dev/best-practices/tracing.md | 265 +++ docs/dev/valkey-direct-access.md | 6 + docs/observability.md | 103 ++ docs/roadmap.md | 142 ++ go.mod | 171 ++ go.sum | 401 +++++ hack/ate-dev-env.sh.example | 41 + hack/boilerplate/go.txt | 14 + hack/boilerplate/python.txt | 14 + hack/boilerplate/yaml.txt | 14 + hack/create-kind-cluster.sh | 101 ++ hack/install-ate-kind.sh | 35 + hack/install-ate.sh | 390 +++++ hack/install-demo-agent-secret.sh | 41 + hack/install-demo-claude-code-multiplex.sh | 97 ++ hack/install-demo-counter.sh | 41 + hack/install-demo-sandbox.sh | 41 + hack/ko.sh | 20 + hack/protoc.sh | 81 + hack/run-e2e.sh | 109 ++ hack/run-tool.sh | 51 + hack/teardown.sh | 123 ++ .../kubernetes/verify-generated.sh | 60 + hack/tools/code-generator/go.mod | 21 + hack/tools/code-generator/go.sum | 20 + hack/tools/controller-gen/go.mod | 52 + hack/tools/controller-gen/go.sum | 225 +++ hack/tools/go-licenses/go.mod | 26 + hack/tools/go-licenses/go.sum | 147 ++ hack/tools/ko/go.mod | 163 ++ hack/tools/ko/go.sum | 595 +++++++ hack/tools/protoc-gen-go-grpc/go.mod | 10 + hack/tools/protoc-gen-go-grpc/go.sum | 16 + hack/tools/protoc-gen-go/go.mod | 7 + hack/tools/protoc-gen-go/go.sum | 4 + hack/tools/setup-envtest/go.mod | 18 + hack/tools/setup-envtest/go.sum | 60 + hack/update-all.sh | 27 + hack/update/README.md | 7 + hack/update/go-mod-tidy.sh | 31 + hack/update/gofmt.sh | 35 + hack/update/licenses.sh | 72 + hack/util/verify-boilerplate.py | 134 ++ hack/verify-all.sh | 27 + hack/verify/README.md | 7 + hack/verify/boilerplate.sh | 24 + hack/verify/go-mod-tidy.sh | 24 + hack/verify/gofmt.sh | 24 + hack/verify/licenses.sh | 24 + internal/ategcs/ategcs.go | 279 ++++ internal/ateompath/ateompath.go | 140 ++ .../controllers/actortemplate_controller.go | 161 ++ internal/controllers/gen.go | 17 + internal/controllers/utils.go | 101 ++ internal/controllers/workerpool_controller.go | 122 ++ internal/credbundle/credbundle.go | 92 ++ internal/dns/corefile.go | 63 + internal/dns/corefile_test.go | 65 + internal/dns/dns.go | 252 +++ internal/dns/dns_test.go | 199 +++ internal/dns/readme.md | 36 + internal/e2e/clients.go | 87 + internal/e2e/env.go | 34 + internal/e2e/env_test.go | 93 ++ internal/e2e/namespace.go | 147 ++ internal/e2e/preflight.go | 65 + internal/e2e/pretty.go | 179 ++ internal/e2e/pretty_test.go | 334 ++++ internal/e2e/readme.md | 39 + internal/e2e/run.go | 74 + internal/e2e/suites/demo/demo_test.go | 162 ++ internal/e2e/suites/demo/testmain_test.go | 24 + internal/e2e/suites/example/example_test.go | 23 + internal/e2e/suites/example/testmain_test.go | 39 + internal/e2e/testmain.go | 74 + internal/k8sjwt/k8sjwt.go | 450 +++++ internal/localca/localca.go | 152 ++ .../localjwtauthority/localjwtauthority.go | 113 ++ internal/memorypullcache/memorypullcache.go | 217 +++ .../memorypullcache/memorypullcache_test.go | 84 + .../podidentitysigner/podidentitysigner.go | 176 ++ internal/rendezvous/rendezvous.go | 281 ++++ internal/resources/actor.go | 47 + internal/resources/actor_test.go | 45 + internal/servicednssigner/servicednssigner.go | 213 +++ internal/sessionidjwt/sessionidjwt.go | 170 ++ internal/signercontroller/signercontroller.go | 249 +++ internal/utils/utils.go | 42 + manifests/agent-secret/agent-secret.yaml.tmpl | 53 + manifests/ate-install/ate-api-server.yaml | 172 ++ manifests/ate-install/ate-controller.yaml | 89 + .../ate-install/ate-system-namespace.yaml | 18 + manifests/ate-install/atelet.yaml | 98 ++ manifests/ate-install/atenet-dns.yaml | 176 ++ manifests/ate-install/atenet-router.yaml | 191 +++ .../generated/ate.dev_actortemplates.yaml | 468 ++++++ .../generated/ate.dev_workerpools.yaml | 79 + manifests/ate-install/generated/role.yaml | 82 + .../kind/atelet/kustomization.yaml | 49 + manifests/ate-install/kind/kustomization.yaml | 26 + manifests/ate-install/kind/rustfs.yaml | 91 ++ .../pod-certificate-controller.yaml | 196 +++ manifests/ate-install/valkey.yaml | 213 +++ .../claude-code-multiplex.yaml.tmpl | 148 ++ manifests/counter/counter.yaml.tmpl | 55 + manifests/sandbox/sandbox.yaml.tmpl | 56 + pkg/client/clientset/versioned/clientset.go | 118 ++ .../versioned/fake/clientset_generated.go | 103 ++ pkg/client/clientset/versioned/fake/doc.go | 18 + .../clientset/versioned/fake/register.go | 54 + pkg/client/clientset/versioned/scheme/doc.go | 18 + .../clientset/versioned/scheme/register.go | 54 + .../typed/api/v1alpha1/actortemplate.go | 68 + .../typed/api/v1alpha1/api_client.go | 104 ++ .../versioned/typed/api/v1alpha1/doc.go | 18 + .../versioned/typed/api/v1alpha1/fake/doc.go | 18 + .../api/v1alpha1/fake/fake_actortemplate.go | 50 + .../api/v1alpha1/fake/fake_api_client.go | 42 + .../api/v1alpha1/fake/fake_workerpool.go | 48 + .../typed/api/v1alpha1/generated_expansion.go | 21 + .../typed/api/v1alpha1/workerpool.go | 68 + .../externalversions/api/interface.go | 44 + .../api/v1alpha1/actortemplate.go | 100 ++ .../api/v1alpha1/interface.go | 50 + .../api/v1alpha1/workerpool.go | 100 ++ .../informers/externalversions/factory.go | 261 +++ .../informers/externalversions/generic.go | 62 + .../internalinterfaces/factory_interfaces.go | 38 + .../listers/api/v1alpha1/actortemplate.go | 68 + .../api/v1alpha1/expansion_generated.go | 33 + pkg/client/listers/api/v1alpha1/workerpool.go | 68 + proto/ateapipb/ateapi.pb.go | 1448 +++++++++++++++++ proto/ateapipb/ateapi.proto | 226 +++ proto/ateapipb/ateapi_grpc.pb.go | 609 +++++++ proto/ateapipb/gen.go | 17 + proto/ateletpb/atelet.pb.go | 969 +++++++++++ proto/ateletpb/atelet.proto | 141 ++ proto/ateletpb/atelet_grpc.pb.go | 223 +++ proto/ateletpb/gen.go | 17 + proto/ateompb/ateom.pb.go | 593 +++++++ proto/ateompb/ateom.proto | 111 ++ proto/ateompb/ateom_grpc.pb.go | 255 +++ proto/ateompb/gen.go | 17 + 491 files changed, 65115 insertions(+) create mode 100644 .agents/skills/agents-md/SKILL.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/pr-workflow.yaml create mode 100644 .gitignore create mode 100644 .ko.yaml create mode 100644 AGENTS.md create mode 100644 COLLABORATING.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 LICENSES/cel.dev/expr/LICENSE create mode 100644 LICENSES/cloud.google.com/go/auth/LICENSE create mode 100644 LICENSES/cloud.google.com/go/auth/oauth2adapt/LICENSE create mode 100644 LICENSES/cloud.google.com/go/compute/metadata/LICENSE create mode 100644 LICENSES/cloud.google.com/go/container/LICENSE create mode 100644 LICENSES/cloud.google.com/go/iam/LICENSE create mode 100644 LICENSES/cloud.google.com/go/internal/LICENSE create mode 100644 LICENSES/cloud.google.com/go/longrunning/LICENSE create mode 100644 LICENSES/cloud.google.com/go/monitoring/LICENSE create mode 100644 LICENSES/cloud.google.com/go/resourcemanager/LICENSE create mode 100644 LICENSES/cloud.google.com/go/serviceusage/LICENSE create mode 100644 LICENSES/cloud.google.com/go/storage/LICENSE create mode 100644 LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp/LICENSE create mode 100644 LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric/LICENSE create mode 100644 LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping/LICENSE create mode 100644 LICENSES/github.com/alicebob/miniredis/v2/LICENSE create mode 100644 LICENSES/github.com/alicebob/miniredis/v2/fpconv/LICENSE.txt create mode 100644 LICENSES/github.com/alicebob/miniredis/v2/geohash/LICENSE create mode 100644 LICENSES/github.com/alicebob/miniredis/v2/gopher-json/LICENSE create mode 100644 LICENSES/github.com/alicebob/miniredis/v2/hyperloglog/LICENSE create mode 100644 LICENSES/github.com/alicebob/miniredis/v2/metro/LICENSE create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/NOTICE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/config/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/credentials/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/internal/configsources/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/LICENSE create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/internal/v4a/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/checksum/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/s3/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/signin/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/sso/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/ssooidc/LICENSE.txt create mode 100644 LICENSES/github.com/aws/aws-sdk-go-v2/service/sts/LICENSE.txt create mode 100644 LICENSES/github.com/aws/smithy-go/LICENSE create mode 100644 LICENSES/github.com/aws/smithy-go/NOTICE create mode 100644 LICENSES/github.com/aws/smithy-go/internal/sync/singleflight/LICENSE create mode 100644 LICENSES/github.com/beorn7/perks/quantile/LICENSE create mode 100644 LICENSES/github.com/cenkalti/backoff/v5/LICENSE create mode 100644 LICENSES/github.com/cespare/xxhash/v2/LICENSE.txt create mode 100644 LICENSES/github.com/cncf/xds/go/LICENSE create mode 100644 LICENSES/github.com/containerd/stargz-snapshotter/estargz/LICENSE create mode 100644 LICENSES/github.com/davecgh/go-spew/spew/LICENSE create mode 100644 LICENSES/github.com/dgryski/go-rendezvous/LICENSE create mode 100644 LICENSES/github.com/docker/cli/cli/config/LICENSE create mode 100644 LICENSES/github.com/docker/cli/cli/config/NOTICE create mode 100644 LICENSES/github.com/docker/docker-credential-helpers/LICENSE create mode 100644 LICENSES/github.com/emicklei/go-restful/v3/LICENSE create mode 100644 LICENSES/github.com/envoyproxy/go-control-plane/envoy/LICENSE create mode 100644 LICENSES/github.com/envoyproxy/go-control-plane/pkg/LICENSE create mode 100644 LICENSES/github.com/envoyproxy/go-control-plane/ratelimit/service/ratelimit/v3/LICENSE create mode 100644 LICENSES/github.com/envoyproxy/protoc-gen-validate/validate/LICENSE create mode 100644 LICENSES/github.com/evanphx/json-patch/v5/LICENSE create mode 100644 LICENSES/github.com/felixge/httpsnoop/LICENSE.txt create mode 100644 LICENSES/github.com/fsnotify/fsnotify/LICENSE create mode 100644 LICENSES/github.com/fxamacker/cbor/v2/LICENSE create mode 100644 LICENSES/github.com/go-jose/go-jose/v4/LICENSE create mode 100644 LICENSES/github.com/go-jose/go-jose/v4/json/LICENSE create mode 100644 LICENSES/github.com/go-logr/logr/LICENSE create mode 100644 LICENSES/github.com/go-logr/stdr/LICENSE create mode 100644 LICENSES/github.com/go-logr/zapr/LICENSE create mode 100644 LICENSES/github.com/go-openapi/jsonpointer/LICENSE create mode 100644 LICENSES/github.com/go-openapi/jsonpointer/NOTICE create mode 100644 LICENSES/github.com/go-openapi/jsonreference/LICENSE create mode 100644 LICENSES/github.com/go-openapi/jsonreference/NOTICE create mode 100644 LICENSES/github.com/go-openapi/swag/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/cmdutils/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/conv/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/fileutils/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/jsonname/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/jsonutils/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/loading/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/mangling/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/netutils/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/stringutils/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/typeutils/LICENSE create mode 100644 LICENSES/github.com/go-openapi/swag/yamlutils/LICENSE create mode 100644 LICENSES/github.com/google/btree/LICENSE create mode 100644 LICENSES/github.com/google/gnostic-models/LICENSE create mode 100644 LICENSES/github.com/google/go-cmp/cmp/LICENSE create mode 100644 LICENSES/github.com/google/go-containerregistry/LICENSE create mode 100644 LICENSES/github.com/google/s2a-go/LICENSE.md create mode 100644 LICENSES/github.com/google/uuid/LICENSE create mode 100644 LICENSES/github.com/googleapis/enterprise-certificate-proxy/client/LICENSE create mode 100644 LICENSES/github.com/googleapis/gax-go/v2/LICENSE create mode 100644 LICENSES/github.com/gorilla/websocket/LICENSE create mode 100644 LICENSES/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE create mode 100644 LICENSES/github.com/hashicorp/go-reap/.gitignore create mode 100644 LICENSES/github.com/hashicorp/go-reap/LICENSE create mode 100644 LICENSES/github.com/hashicorp/go-reap/README.md create mode 100644 LICENSES/github.com/hashicorp/go-reap/reap.go create mode 100644 LICENSES/github.com/hashicorp/go-reap/reap_stub.go create mode 100644 LICENSES/github.com/hashicorp/go-reap/reap_stub_test.go create mode 100644 LICENSES/github.com/hashicorp/go-reap/reap_unix.go create mode 100644 LICENSES/github.com/hashicorp/go-reap/reap_unix_test.go create mode 100644 LICENSES/github.com/json-iterator/go/LICENSE create mode 100644 LICENSES/github.com/klauspost/compress/LICENSE create mode 100644 LICENSES/github.com/klauspost/compress/internal/snapref/LICENSE create mode 100644 LICENSES/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt create mode 100644 LICENSES/github.com/mitchellh/go-homedir/LICENSE create mode 100644 LICENSES/github.com/moby/spdystream/LICENSE create mode 100644 LICENSES/github.com/moby/spdystream/NOTICE create mode 100644 LICENSES/github.com/moby/spdystream/spdy/LICENSE create mode 100644 LICENSES/github.com/modern-go/concurrent/LICENSE create mode 100644 LICENSES/github.com/modern-go/reflect2/LICENSE create mode 100644 LICENSES/github.com/munnerz/goautoneg/LICENSE create mode 100644 LICENSES/github.com/opencontainers/go-digest/LICENSE create mode 100644 LICENSES/github.com/opencontainers/image-spec/specs-go/LICENSE create mode 100644 LICENSES/github.com/opencontainers/runtime-spec/specs-go/LICENSE create mode 100644 LICENSES/github.com/pmezard/go-difflib/difflib/LICENSE create mode 100644 LICENSES/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/LICENSE create mode 100644 LICENSES/github.com/prometheus/client_golang/prometheus/LICENSE create mode 100644 LICENSES/github.com/prometheus/client_golang/prometheus/NOTICE create mode 100644 LICENSES/github.com/prometheus/client_model/go/LICENSE create mode 100644 LICENSES/github.com/prometheus/client_model/go/NOTICE create mode 100644 LICENSES/github.com/prometheus/common/LICENSE create mode 100644 LICENSES/github.com/prometheus/common/NOTICE create mode 100644 LICENSES/github.com/prometheus/otlptranslator/LICENSE create mode 100644 LICENSES/github.com/prometheus/procfs/LICENSE create mode 100644 LICENSES/github.com/prometheus/procfs/NOTICE create mode 100644 LICENSES/github.com/redis/go-redis/v9/LICENSE create mode 100644 LICENSES/github.com/sirupsen/logrus/LICENSE create mode 100644 LICENSES/github.com/spf13/cobra/LICENSE.txt create mode 100644 LICENSES/github.com/spf13/pflag/LICENSE create mode 100644 LICENSES/github.com/spiffe/go-spiffe/v2/LICENSE create mode 100644 LICENSES/github.com/vbatts/tar-split/archive/tar/LICENSE create mode 100644 LICENSES/github.com/vishvananda/netlink/LICENSE create mode 100644 LICENSES/github.com/vishvananda/netns/LICENSE create mode 100644 LICENSES/github.com/x448/float16/LICENSE create mode 100644 LICENSES/github.com/yuin/gopher-lua/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/auto/sdk/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/contrib/detectors/gcp/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/exporters/prometheus/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/metric/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/sdk/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/sdk/metric/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/otel/trace/LICENSE create mode 100644 LICENSES/go.opentelemetry.io/proto/otlp/LICENSE create mode 100644 LICENSES/go.uber.org/atomic/LICENSE.txt create mode 100644 LICENSES/go.uber.org/multierr/LICENSE.txt create mode 100644 LICENSES/go.uber.org/zap/LICENSE create mode 100644 LICENSES/go.yaml.in/yaml/v2/LICENSE create mode 100644 LICENSES/go.yaml.in/yaml/v2/NOTICE create mode 100644 LICENSES/go.yaml.in/yaml/v3/LICENSE create mode 100644 LICENSES/go.yaml.in/yaml/v3/NOTICE create mode 100644 LICENSES/golang.org/x/crypto/LICENSE create mode 100644 LICENSES/golang.org/x/net/LICENSE create mode 100644 LICENSES/golang.org/x/oauth2/LICENSE create mode 100644 LICENSES/golang.org/x/sync/LICENSE create mode 100644 LICENSES/golang.org/x/sys/LICENSE create mode 100644 LICENSES/golang.org/x/sys/unix/LICENSE create mode 100644 LICENSES/golang.org/x/term/LICENSE create mode 100644 LICENSES/golang.org/x/text/LICENSE create mode 100644 LICENSES/golang.org/x/time/rate/LICENSE create mode 100644 LICENSES/gomodules.xyz/jsonpatch/v2/LICENSE create mode 100644 LICENSES/google.golang.org/api/LICENSE create mode 100644 LICENSES/google.golang.org/api/internal/third_party/uritemplates/LICENSE create mode 100644 LICENSES/google.golang.org/genproto/googleapis/api/LICENSE create mode 100644 LICENSES/google.golang.org/genproto/googleapis/rpc/LICENSE create mode 100644 LICENSES/google.golang.org/genproto/googleapis/type/LICENSE create mode 100644 LICENSES/google.golang.org/grpc/LICENSE create mode 100644 LICENSES/google.golang.org/grpc/NOTICE.txt create mode 100644 LICENSES/google.golang.org/protobuf/LICENSE create mode 100644 LICENSES/gopkg.in/evanphx/json-patch.v4/LICENSE create mode 100644 LICENSES/gopkg.in/inf.v0/LICENSE create mode 100644 LICENSES/k8s.io/api/LICENSE create mode 100644 LICENSES/k8s.io/apiextensions-apiserver/pkg/LICENSE create mode 100644 LICENSES/k8s.io/apimachinery/pkg/LICENSE create mode 100644 LICENSES/k8s.io/apimachinery/third_party/forked/golang/LICENSE create mode 100644 LICENSES/k8s.io/client-go/LICENSE create mode 100644 LICENSES/k8s.io/klog/v2/LICENSE create mode 100644 LICENSES/k8s.io/kube-openapi/pkg/LICENSE create mode 100644 LICENSES/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE create mode 100644 LICENSES/k8s.io/kube-openapi/pkg/validation/spec/LICENSE create mode 100644 LICENSES/k8s.io/streaming/pkg/LICENSE create mode 100644 LICENSES/k8s.io/utils/LICENSE create mode 100644 LICENSES/k8s.io/utils/internal/third_party/forked/golang/LICENSE create mode 100644 LICENSES/sigs.k8s.io/controller-runtime/LICENSE create mode 100644 LICENSES/sigs.k8s.io/json/LICENSE create mode 100644 LICENSES/sigs.k8s.io/randfill/LICENSE create mode 100644 LICENSES/sigs.k8s.io/randfill/NOTICE create mode 100644 LICENSES/sigs.k8s.io/structured-merge-diff/v6/LICENSE create mode 100644 LICENSES/sigs.k8s.io/yaml/LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 api/v1alpha1/actortemplate_types.go create mode 100644 api/v1alpha1/actortemplate_types_test.go create mode 100644 api/v1alpha1/gen.go create mode 100644 api/v1alpha1/groupversion_info.go create mode 100644 api/v1alpha1/workerpool_types.go create mode 100644 api/v1alpha1/zz_generated.deepcopy.go create mode 100644 benchmarking/README.md create mode 100644 benchmarking/locust/Dockerfile create mode 100644 benchmarking/locust/__init__.py create mode 100755 benchmarking/locust/build_and_push.sh create mode 100644 benchmarking/locust/common/__init__.py create mode 100644 benchmarking/locust/common/ateapi_pb2.py create mode 100644 benchmarking/locust/common/ateapi_pb2_grpc.py create mode 100644 benchmarking/locust/common/metrics.py create mode 100644 benchmarking/locust/common/trace.py create mode 100644 benchmarking/locust/common/wait_time.py create mode 100755 benchmarking/locust/deploy_locust.sh create mode 100755 benchmarking/locust/generate_protos.sh create mode 100644 benchmarking/locust/manifests/all.yaml create mode 100644 benchmarking/locust/manifests/ate-api.yaml create mode 100644 benchmarking/locust/manifests/counter-demo.yaml create mode 100644 benchmarking/locust/manifests/workloads.yaml create mode 100644 benchmarking/locust/requirements.txt create mode 100644 benchmarking/locust/shapes/__init__.py create mode 100644 benchmarking/locust/shapes/burst_shape.py create mode 100644 benchmarking/locust/tests/__init__.py create mode 100644 benchmarking/locust/tests/ate_api.py create mode 100644 benchmarking/locust/tests/counter_demo.py create mode 100644 benchmarking/locust/tests/kernelmem.py create mode 100644 benchmarking/locust/tests/sleep.py create mode 100644 benchmarking/locust/tests/usermem.py create mode 100644 benchmarking/monitoring.yaml create mode 100755 benchmarking/workloads/deploy.sh create mode 100644 benchmarking/workloads/manifests/full_workloads.yaml.tmpl create mode 100644 benchmarking/workloads/manifests/workloads.yaml.tmpl create mode 100644 cmd/kubectl-ate/README.md create mode 100644 cmd/kubectl-ate/cmd/admin.go create mode 100644 cmd/kubectl-ate/cmd/admin_debug_redis_flush.go create mode 100644 cmd/kubectl-ate/cmd/admin_make_ca_pool.go create mode 100644 cmd/kubectl-ate/cmd/admin_make_jwt_pool.go create mode 100644 cmd/kubectl-ate/cmd/create.go create mode 100644 cmd/kubectl-ate/cmd/create_actor.go create mode 100644 cmd/kubectl-ate/cmd/delete.go create mode 100644 cmd/kubectl-ate/cmd/delete_actor.go create mode 100644 cmd/kubectl-ate/cmd/get.go create mode 100644 cmd/kubectl-ate/cmd/get_actors.go create mode 100644 cmd/kubectl-ate/cmd/get_workers.go create mode 100644 cmd/kubectl-ate/cmd/logs.go create mode 100644 cmd/kubectl-ate/cmd/logs_actors.go create mode 100644 cmd/kubectl-ate/cmd/logs_actors_test.go create mode 100644 cmd/kubectl-ate/cmd/resume.go create mode 100644 cmd/kubectl-ate/cmd/resume_actor.go create mode 100644 cmd/kubectl-ate/cmd/root.go create mode 100644 cmd/kubectl-ate/cmd/suspend.go create mode 100644 cmd/kubectl-ate/cmd/suspend_actor.go create mode 100644 cmd/kubectl-ate/main.go create mode 100644 cmd/kubectl-ate/pkg/client/builder.go create mode 100644 cmd/kubectl-ate/pkg/printer/printer.go create mode 100644 cmd/kubectl-ate/pkg/printer/printer_test.go create mode 100644 cmd/servers/ateapi/ateapi.go create mode 100644 cmd/servers/ateapi/controlapi/create_actor.go create mode 100644 cmd/servers/ateapi/controlapi/debug_clear.go create mode 100644 cmd/servers/ateapi/controlapi/delete_actor.go create mode 100644 cmd/servers/ateapi/controlapi/dialer.go create mode 100644 cmd/servers/ateapi/controlapi/functional_test.go create mode 100644 cmd/servers/ateapi/controlapi/get_actor.go create mode 100644 cmd/servers/ateapi/controlapi/informer.go create mode 100644 cmd/servers/ateapi/controlapi/list_actors.go create mode 100644 cmd/servers/ateapi/controlapi/list_workers.go create mode 100644 cmd/servers/ateapi/controlapi/resume_actor.go create mode 100644 cmd/servers/ateapi/controlapi/service.go create mode 100644 cmd/servers/ateapi/controlapi/service_test.go create mode 100644 cmd/servers/ateapi/controlapi/suspend_actor.go create mode 100644 cmd/servers/ateapi/controlapi/syncer.go create mode 100644 cmd/servers/ateapi/controlapi/syncer_test.go create mode 100644 cmd/servers/ateapi/controlapi/workflow.go create mode 100644 cmd/servers/ateapi/controlapi/workflow_resume.go create mode 100644 cmd/servers/ateapi/controlapi/workflow_suspend.go create mode 100644 cmd/servers/ateapi/sessionidentity/sessionidentity.go create mode 100644 cmd/servers/ateapi/store/ateredis/ateredis.go create mode 100644 cmd/servers/ateapi/store/ateredis/ateredis_test.go create mode 100644 cmd/servers/ateapi/store/store.go create mode 100644 cmd/servers/ateapi/store/storetest/storetest.go create mode 100644 cmd/servers/atecontroller/main.go create mode 100644 cmd/servers/atelet/atelet.go create mode 100644 cmd/servers/atelet/oci.go create mode 100644 cmd/servers/atenet/app/dns/cmd.go create mode 100644 cmd/servers/atenet/app/root.go create mode 100644 cmd/servers/atenet/app/router/atstore.go create mode 100644 cmd/servers/atenet/app/router/atstore_file.go create mode 100644 cmd/servers/atenet/app/router/atstore_test.go create mode 100644 cmd/servers/atenet/app/router/controller.go create mode 100644 cmd/servers/atenet/app/router/dashboard.html create mode 100644 cmd/servers/atenet/app/router/envoyrunner.go create mode 100644 cmd/servers/atenet/app/router/extproc.go create mode 100644 cmd/servers/atenet/app/router/extproc_in.go create mode 100644 cmd/servers/atenet/app/router/extproc_in_test.go create mode 100644 cmd/servers/atenet/app/router/extproc_out.go create mode 100644 cmd/servers/atenet/app/router/extproc_test.go create mode 100644 cmd/servers/atenet/app/router/health.go create mode 100644 cmd/servers/atenet/app/router/readme.md create mode 100644 cmd/servers/atenet/app/router/resumer.go create mode 100644 cmd/servers/atenet/app/router/resumer_test.go create mode 100644 cmd/servers/atenet/app/router/router.go create mode 100644 cmd/servers/atenet/app/router/status.go create mode 100644 cmd/servers/atenet/app/router/status_test.go create mode 100644 cmd/servers/atenet/app/router/xds.go create mode 100644 cmd/servers/atenet/app/router/xds_test.go create mode 100644 cmd/servers/atenet/atenet-diagram.png create mode 100644 cmd/servers/atenet/main.go create mode 100644 cmd/servers/atenet/readme.md create mode 100644 cmd/servers/ateom-gvisor/ateom-gvisor.go create mode 100644 cmd/servers/ateom-gvisor/logger.go create mode 100644 cmd/servers/ateom-gvisor/logger_test.go create mode 100644 cmd/servers/ateom-gvisor/runsc.go create mode 100644 cmd/servers/ateom-gvisor/stopwatch.go create mode 100644 cmd/servers/podcertcontroller/podcertcontroller.go create mode 100644 cmd/setup/cmd/api.go create mode 100644 cmd/setup/cmd/bucket.go create mode 100644 cmd/setup/cmd/cluster.go create mode 100644 cmd/setup/cmd/common.go create mode 100644 cmd/setup/cmd/iam.go create mode 100644 cmd/setup/cmd/root.go create mode 100644 cmd/setup/main.go create mode 100644 code-of-conduct.md create mode 100644 demos/agent-secret/README.md create mode 100644 demos/agent-secret/main.go create mode 100644 demos/claude-code-multiplex/README.md create mode 100644 demos/claude-code-multiplex/ui/index.html create mode 100644 demos/claude-code-multiplex/ui/server.go create mode 100644 demos/claude-code-multiplex/workload/Dockerfile create mode 100755 demos/claude-code-multiplex/workload/run.sh create mode 100644 demos/counter/.gitignore create mode 100644 demos/counter/README.md create mode 100644 demos/counter/counter.go create mode 100644 demos/sandbox/.gitignore create mode 100644 demos/sandbox/README.md create mode 100644 demos/sandbox/client/main.go create mode 100644 demos/sandbox/main.go create mode 100644 docs/api-guide.md create mode 100644 docs/architecture.md create mode 100644 docs/dev/best-practices/tracing.md create mode 100644 docs/dev/valkey-direct-access.md create mode 100644 docs/observability.md create mode 100644 docs/roadmap.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 hack/ate-dev-env.sh.example create mode 100644 hack/boilerplate/go.txt create mode 100644 hack/boilerplate/python.txt create mode 100644 hack/boilerplate/yaml.txt create mode 100755 hack/create-kind-cluster.sh create mode 100755 hack/install-ate-kind.sh create mode 100755 hack/install-ate.sh create mode 100644 hack/install-demo-agent-secret.sh create mode 100644 hack/install-demo-claude-code-multiplex.sh create mode 100644 hack/install-demo-counter.sh create mode 100644 hack/install-demo-sandbox.sh create mode 100755 hack/ko.sh create mode 100755 hack/protoc.sh create mode 100755 hack/run-e2e.sh create mode 100755 hack/run-tool.sh create mode 100755 hack/teardown.sh create mode 100755 hack/third_party/kubernetes/verify-generated.sh create mode 100644 hack/tools/code-generator/go.mod create mode 100644 hack/tools/code-generator/go.sum create mode 100644 hack/tools/controller-gen/go.mod create mode 100644 hack/tools/controller-gen/go.sum create mode 100644 hack/tools/go-licenses/go.mod create mode 100644 hack/tools/go-licenses/go.sum create mode 100644 hack/tools/ko/go.mod create mode 100644 hack/tools/ko/go.sum create mode 100644 hack/tools/protoc-gen-go-grpc/go.mod create mode 100644 hack/tools/protoc-gen-go-grpc/go.sum create mode 100644 hack/tools/protoc-gen-go/go.mod create mode 100644 hack/tools/protoc-gen-go/go.sum create mode 100644 hack/tools/setup-envtest/go.mod create mode 100644 hack/tools/setup-envtest/go.sum create mode 100755 hack/update-all.sh create mode 100644 hack/update/README.md create mode 100755 hack/update/go-mod-tidy.sh create mode 100755 hack/update/gofmt.sh create mode 100755 hack/update/licenses.sh create mode 100755 hack/util/verify-boilerplate.py create mode 100755 hack/verify-all.sh create mode 100644 hack/verify/README.md create mode 100755 hack/verify/boilerplate.sh create mode 100755 hack/verify/go-mod-tidy.sh create mode 100755 hack/verify/gofmt.sh create mode 100755 hack/verify/licenses.sh create mode 100644 internal/ategcs/ategcs.go create mode 100644 internal/ateompath/ateompath.go create mode 100644 internal/controllers/actortemplate_controller.go create mode 100644 internal/controllers/gen.go create mode 100644 internal/controllers/utils.go create mode 100644 internal/controllers/workerpool_controller.go create mode 100644 internal/credbundle/credbundle.go create mode 100644 internal/dns/corefile.go create mode 100644 internal/dns/corefile_test.go create mode 100644 internal/dns/dns.go create mode 100644 internal/dns/dns_test.go create mode 100644 internal/dns/readme.md create mode 100644 internal/e2e/clients.go create mode 100644 internal/e2e/env.go create mode 100644 internal/e2e/env_test.go create mode 100644 internal/e2e/namespace.go create mode 100644 internal/e2e/preflight.go create mode 100644 internal/e2e/pretty.go create mode 100644 internal/e2e/pretty_test.go create mode 100644 internal/e2e/readme.md create mode 100644 internal/e2e/run.go create mode 100644 internal/e2e/suites/demo/demo_test.go create mode 100644 internal/e2e/suites/demo/testmain_test.go create mode 100644 internal/e2e/suites/example/example_test.go create mode 100644 internal/e2e/suites/example/testmain_test.go create mode 100644 internal/e2e/testmain.go create mode 100644 internal/k8sjwt/k8sjwt.go create mode 100644 internal/localca/localca.go create mode 100644 internal/localjwtauthority/localjwtauthority.go create mode 100644 internal/memorypullcache/memorypullcache.go create mode 100644 internal/memorypullcache/memorypullcache_test.go create mode 100644 internal/podidentitysigner/podidentitysigner.go create mode 100644 internal/rendezvous/rendezvous.go create mode 100644 internal/resources/actor.go create mode 100644 internal/resources/actor_test.go create mode 100644 internal/servicednssigner/servicednssigner.go create mode 100644 internal/sessionidjwt/sessionidjwt.go create mode 100644 internal/signercontroller/signercontroller.go create mode 100644 internal/utils/utils.go create mode 100644 manifests/agent-secret/agent-secret.yaml.tmpl create mode 100644 manifests/ate-install/ate-api-server.yaml create mode 100644 manifests/ate-install/ate-controller.yaml create mode 100644 manifests/ate-install/ate-system-namespace.yaml create mode 100644 manifests/ate-install/atelet.yaml create mode 100644 manifests/ate-install/atenet-dns.yaml create mode 100644 manifests/ate-install/atenet-router.yaml create mode 100644 manifests/ate-install/generated/ate.dev_actortemplates.yaml create mode 100644 manifests/ate-install/generated/ate.dev_workerpools.yaml create mode 100644 manifests/ate-install/generated/role.yaml create mode 100644 manifests/ate-install/kind/atelet/kustomization.yaml create mode 100644 manifests/ate-install/kind/kustomization.yaml create mode 100644 manifests/ate-install/kind/rustfs.yaml create mode 100644 manifests/ate-install/pod-certificate-controller.yaml create mode 100644 manifests/ate-install/valkey.yaml create mode 100644 manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl create mode 100644 manifests/counter/counter.yaml.tmpl create mode 100644 manifests/sandbox/sandbox.yaml.tmpl create mode 100644 pkg/client/clientset/versioned/clientset.go create mode 100644 pkg/client/clientset/versioned/fake/clientset_generated.go create mode 100644 pkg/client/clientset/versioned/fake/doc.go create mode 100644 pkg/client/clientset/versioned/fake/register.go create mode 100644 pkg/client/clientset/versioned/scheme/doc.go create mode 100644 pkg/client/clientset/versioned/scheme/register.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/actortemplate.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/api_client.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/doc.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/fake/doc.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_actortemplate.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_api_client.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_workerpool.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/generated_expansion.go create mode 100644 pkg/client/clientset/versioned/typed/api/v1alpha1/workerpool.go create mode 100644 pkg/client/informers/externalversions/api/interface.go create mode 100644 pkg/client/informers/externalversions/api/v1alpha1/actortemplate.go create mode 100644 pkg/client/informers/externalversions/api/v1alpha1/interface.go create mode 100644 pkg/client/informers/externalversions/api/v1alpha1/workerpool.go create mode 100644 pkg/client/informers/externalversions/factory.go create mode 100644 pkg/client/informers/externalversions/generic.go create mode 100644 pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go create mode 100644 pkg/client/listers/api/v1alpha1/actortemplate.go create mode 100644 pkg/client/listers/api/v1alpha1/expansion_generated.go create mode 100644 pkg/client/listers/api/v1alpha1/workerpool.go create mode 100644 proto/ateapipb/ateapi.pb.go create mode 100644 proto/ateapipb/ateapi.proto create mode 100644 proto/ateapipb/ateapi_grpc.pb.go create mode 100644 proto/ateapipb/gen.go create mode 100644 proto/ateletpb/atelet.pb.go create mode 100644 proto/ateletpb/atelet.proto create mode 100644 proto/ateletpb/atelet_grpc.pb.go create mode 100644 proto/ateletpb/gen.go create mode 100644 proto/ateompb/ateom.pb.go create mode 100644 proto/ateompb/ateom.proto create mode 100644 proto/ateompb/ateom_grpc.pb.go create mode 100644 proto/ateompb/gen.go diff --git a/.agents/skills/agents-md/SKILL.md b/.agents/skills/agents-md/SKILL.md new file mode 100644 index 000000000..ec6f68167 --- /dev/null +++ b/.agents/skills/agents-md/SKILL.md @@ -0,0 +1,71 @@ +--- +name: agents-md +description: Generates or updates an AGENTS.md file +--- + +Generate or update AGENTS.md files in key folders of the project. +Ensure the target AGENTS.md file accurately reflects the current status of the code. + +## Key Requirements + +There must always be an AGENTS.md file in the project root. +The AGENTS.md file at the root of the project may include the following sections: + +- Project overview +- Build and test commands +- Code style guidelines +- Testing instructions +- Security considerations + +AGENTS.md files in subfolders may be even more concise and specific to those subfolders. + +## Maximize AGENTS.md Performance + +To maximize agent performance and token efficiency, adhere to the following: + +### Progressive Disclosure + +Each AGENTS.md should be short. Approx. 100-150 lines total. +Link to a handful of relevant, focused reference documents in the same repo, as needed. + +### Modularity + +While only one AGENTS.md is allowed per folder, you can create an AGENTS.md file in any folder. +Rather than putting everything in the root AGENTS.md, move highly specific advice to AGENTS.md in the most relevant folders of the project. + +### References + +When documentation that would have helped you is missing, add references in the docs/ folder found at the project root. When these get out of date, update them. + +### Workflows + +When references describe workflows, the tasks should be described as numbered steps. For example: + +1. Get the beep from the boop. +2. Then bop it. + +### Decisions + +When there are multiple ways of doing something in the codebase, use a decision table like the following: + +| Question | Boop | Bop | +| :---- | :---- | :---- | +| Is foo a bar baz? | ✅ | | +| Is foo a quux? | | ✅ | + +### Real Code Examples + +If you think they are particularly good examples, include snippets from actual code in the repo, up to approx. 10 lines in length. +These should only be the most relevant examples and representative of patterns that would be good to repeat in future code. +Their purpose is to improve code reuse by agents, rather than each agent reinventing the wheel. + +### Domain Specific Rules + +If you think it would help, you can include a few simple domain specific rules. +Not too many, or agents will get stuck trying to handle too many rules. +A general example of a domain specific rule is "Use a finance-specific numeric type for any financial calculations." + +### Don't vs. Do + +When adding warnings against doing something, also make a concrete suggestion for the correct approach. +"Don't do X, do Y instead." diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..fee303a63 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,22 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +## Expected Behavior + + +## Actual Behavior + + +## Steps to Reproduce the Problem + +1. +1. +1. + +## Specifications + +- Version: +- Platform: \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..ba31ec05c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +Fixes # + +> It's a good idea to open an issue first for discussion. + +- [ ] Tests pass +- [ ] Appropriate changes to documentation are included in the PR diff --git a/.github/workflows/pr-workflow.yaml b/.github/workflows/pr-workflow.yaml new file mode 100644 index 000000000..a3b26d701 --- /dev/null +++ b/.github/workflows/pr-workflow.yaml @@ -0,0 +1,52 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: pr-workflow +on: + pull_request: +jobs: + run-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: 1.26 + - run: go vet -v ./... + - run: go test -v ./... + - name: verify + run: hack/verify-all.sh + e2e-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: 1.26 + - name: Install kind + run: go install sigs.k8s.io/kind@v0.31.0 + - name: Create cluster + run: hack/create-kind-cluster.sh + - name: Install Agent Substrate + run: hack/install-ate-kind.sh --deploy-ate-system + - name: Wait For Ready + run: kubectl wait pod --all --for=condition=Ready --namespace=ate-system --timeout=300s + - name: Deploy Counter Demo + run: hack/install-ate-kind.sh --deploy-demo-counter + - name: Run E2E tests + run: KO_DOCKER_REPO=localhost:5001 BUCKET_NAME=ate-snapshots KUBECTL_CONTEXT=kind-kind hack/run-e2e.sh -v -args -no-color diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d7afedf39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Binaries +/ateapi +/substratectl +/kubectl-ate +/atelet +/bin/ + +# Python +venv/ +.venv/ +__pycache__/ +*.pyc + +# Local environment variables +.ate-dev-env.sh \ No newline at end of file diff --git a/.ko.yaml b/.ko.yaml new file mode 100644 index 000000000..8814f8a1f --- /dev/null +++ b/.ko.yaml @@ -0,0 +1,19 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +defaultBaseImage: gcr.io/distroless/static-debian11 + +baseImageOverrides: + github.com/agent-substrate/substrate/demos/sandbox: alpine + github.com/agent-substrate/substrate/demos/agent-secret: alpine diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..659e0470b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,49 @@ +# Agent Substrate + +## Project Overview + +Agent Substrate is a system built on top of Kubernetes which manages agent-like workloads to achieve higher scale and efficiency than Kubernetes alone can offer, with lower latency. +It takes the Kubernetes control-plane out of the critical path to achieve lower latency by mapping a larger set of “actors” (applications such as agents) onto a smaller set of ready “workers” (Kubernetes Pods). +Agent Substrate relies on the fact that agent-like applications tend to be idle most of the time to achieve heavy multiplexing. + +For development, it's recommended to read the `README.md` and `CONTRIBUTING.md` in the root folder. +See `hack/install-ate.sh` and `cmd/setup` for provisioning and deploying clusters and GCP resources. + +## Build and Test Commands + +Agent Substrate uses a `Makefile` for its build and test tasks. + +### Building +- **Binaries**: `make build` (builds images and `kubectl-ate`) or `make build-atectl` +- **Images**: `make build-images` (uses ko to build container images) +- **Demos**: `make build-demos` + +### Testing and Verification +- **Run Unit Tests**: `make test` +- **Run E2E Tests**: `make e2e` (Requires GCP cluster setup and built images) +- **Run Linters and Verifiers**: `make verify` (Includes `go vet` and checks for formatting, boilerplate headers, licenses, and go modules) + +## Code Style Guidelines + +- **Go Formatting**: Code must be formatted with `gofmt`. Run `make fmt` to automatically format all files before submitting changes. +- **Copyright Headers**: All files must contain appropriate copyright and license headers. See templates in `hack/boilerplate/`. +- **Modularity**: Submit small, focused Pull Requests that touch a limited part of the codebase for easier reviews and rebasing. +- **Go Modules**: Ensure `go.mod` is clean. Run `go mod tidy` if adding or removing dependencies. + +## Testing Instructions + +1. Write tests for all new code. We will not merge code that lacks tests. +2. Ensure changes do not break existing tests. +3. Run `make verify` locally before requesting a code review to catch common issues like missed copyright headers or formatting drift. +4. For end-to-end tests involving the actual infrastructure, ensure you have a running cluster (setup via `hack/ate-dev-env.sh.example` and `go run ./cmd/setup --all`). + +## Security Considerations + +The security story for Substrate is very early and many features are missing. +However! Take care to respect security best practices when writing code in order to improve Substrate's security over time. +The following is what Substrate currently offers. +Keep this up to date when updating AGENTS.md. + +- **Workload Isolation**: The project uses `gVisor` (`runsc`) for sandboxing and security isolation of workloads on pods. A temporary gVisor patch might be required (check the README instructions). + +For future plans for security, reference `docs/roadmap.md`. diff --git a/COLLABORATING.md b/COLLABORATING.md new file mode 100644 index 000000000..c80f9f56f --- /dev/null +++ b/COLLABORATING.md @@ -0,0 +1,88 @@ +# Collaborating on Agent Substrate + +This project is intended to be "very" open. Especially in the early stages, we +do not have a lot of infrastructure in place to manage the repository, so we are +relying on each other to be good collaborators. To that end, here are some +guidelines for collaborating on this project. + +## Code of conduct + +Please read and internalize our [code of conduct](code-of-conduct.md). We want +this to be a welcoming and inclusive community, and we expect everyone to +adhere to the code of conduct at all times. If you see someone violating the +code of conduct, please report it to the maintainers immediately. We take all +reports seriously and will take appropriate action to address any issues. + +Open, direct, honest communication is encouraged, but always be respectful and +professional. + +## World-wide community + +This project is not limited to one timezone, and we hope to have collaborators +from all over the world. Please be mindful of this at all times. + +This project uses English as the primary language for communication. If +English is not your first language, please do not hesitate to ask for +clarification if you do not understand something. + +## Written communication + +Prefer written communication (PRs, issues, mailing-list) over verbal +communication (e.g. video calls). This allows for people who might not have +been in the conversation to understand why a decision was made the way it was. + +When writing, please strive for clarity and conciseness. Not everyone in the +community will have the same proficiency in English, so please be mindful of +that when writing. + +## Always use Pull Requests + +Do not push directly to the main branch. Always use pull requests to propose +changes to the codebase. This allows for code review and discussion before +changes are merged, which helps maintain the quality of the codebase and +fosters collaboration. + +### Merging PRs + +PRs should be merged by the reviewer of a PR, not the author. + +### Using AI + +Using AI tools to assist with coding is allowed, but please be transparent +about it. Regardless of how a PR was created, the _human_ who is offering the +PR is responsible for the content of the PR, and they should be able to explain +the code and answer questions about it. Please be respectful of your +reviewers' time and do not offer PRs that you cannot explain or defend. If you +use an AI tool to generate a significant fraction of a PR, please note that in +the PR comment. + +## Code reviews + +We want to move quickly, but we need to balance that with quality and +maintainability. Code reviews are an important part of that process. All PRs +should be reviewed BEFORE they are merged. + +### Code reviews across companies + +As this community grows, we expect to see collaborators from different +companies. Whenever possible, we want to encourage code reviews across +companies. This helps foster collaboration and knowledge sharing across the +community, and it helps prevent silos from forming within the community. + +## Working hours + +We want to move quickly, but we also want to be respectful of each other's +time. For the sake of consistency, this project's "working hours" are Monday +to Friday, 8am to 8pm, US Pacific Time (GMT-7). Please avoid merging PRs late +at night or on weekends, unless it is an urgent fix. This allows for people to +have a better work-life balance and prevents burnout. If you do need to merge +something outside of normal working hours, please try to give a heads up to the +rest of the community so that they are aware. + +## Ownership + +As this project grows, we hope to see more and more collaborators. We want to +encourage a culture of ownership, where people demonstrate ownership of various +parts of the codebase - a file, a package, a subsystem. We should all try to +respect each other's ownership, but we must not become territorial. Everyone +should be ready to track an issue or feature across the code as needed. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..8d95b53e0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# How to Contribute + +We would love to accept your patches and contributions to this project. Before +you spend a lot of time on a contribution, please review the following +guidelines. + +## Before you begin + +### Sign our Contributor License Agreement + +Contributions to this project must be accompanied by a +[Contributor License Agreement](https://cla.developers.google.com/about) (CLA). +You (or your employer) retain the copyright to your contribution; this simply +gives us permission to use and redistribute your contributions as part of the +project. + +If you or your current employer have already signed the Google CLA (even if it +was for a different project), you probably don't need to do it again. + +Visit to see your current agreements or to +sign a new one. + +### Review our Community Guidelines + +This project follows [Google's Open Source Community +Guidelines](https://opensource.google/conduct/). + +## Contribution process + +This is a very new project, so we are still working out exactly how it is going +to be developed. For now, we are focused on iterating quickly to find the right +design and architecture. This has implications for contributors: + +1) Things are moving quickly, so PRs may need to be rebased or updated +frequently. Small PRs that are focused on a single issue or feature are easier +to review and update than large PRs that touch many different parts of the +codebase. + +2) While we welcome new contributors, we are really focused on the minimal +capabilities needed to make this project useful. Before you start a new +contribution, please discuss it with us first (if there is an issue open, +comment there and if not, open one). We want to make sure that your work is +aligned with our near-term goals for the project and that we are not +duplicating work that is already in flight. + +3) PRs which are not aligned with our near-term goals may be closed without +extensive review. We are not trying to be discouraging, but we need to make +sure that we are focused on the most important work. + +### Code Reviews + +All submissions, including submissions by project members, require review. We +use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests) +for this purpose. + +All code changes should be accompanied by tests. We will not merge code that +does not have tests, and we will not merge code that causes tests to fail. + +### Copyright Headers + +Every file containing source code must include copyright and license +information. This includes any JS/CSS files that you might be serving out to +browsers. (This is to help well-intentioned people avoid accidental copying +that doesn't comply with the license.) + +Our standard headers for various filetypes can be found in +[./hack/boilerplate](./hack/boilerplate/). diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..30c342353 --- /dev/null +++ b/LICENSE @@ -0,0 +1,206 @@ +<<<<<<< HEAD +||||||| (empty tree) +======= + +>>>>>>> e2a9125 (Initial commit of Agent Substrate) + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cel.dev/expr/LICENSE b/LICENSES/cel.dev/expr/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cel.dev/expr/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/auth/LICENSE b/LICENSES/cloud.google.com/go/auth/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/auth/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/auth/oauth2adapt/LICENSE b/LICENSES/cloud.google.com/go/auth/oauth2adapt/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/auth/oauth2adapt/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/compute/metadata/LICENSE b/LICENSES/cloud.google.com/go/compute/metadata/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/compute/metadata/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/container/LICENSE b/LICENSES/cloud.google.com/go/container/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/container/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/iam/LICENSE b/LICENSES/cloud.google.com/go/iam/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/iam/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/internal/LICENSE b/LICENSES/cloud.google.com/go/internal/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/internal/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/longrunning/LICENSE b/LICENSES/cloud.google.com/go/longrunning/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/longrunning/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/monitoring/LICENSE b/LICENSES/cloud.google.com/go/monitoring/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/monitoring/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/resourcemanager/LICENSE b/LICENSES/cloud.google.com/go/resourcemanager/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/resourcemanager/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/serviceusage/LICENSE b/LICENSES/cloud.google.com/go/serviceusage/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/serviceusage/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/cloud.google.com/go/storage/LICENSE b/LICENSES/cloud.google.com/go/storage/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/cloud.google.com/go/storage/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp/LICENSE b/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric/LICENSE b/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping/LICENSE b/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/alicebob/miniredis/v2/LICENSE b/LICENSES/github.com/alicebob/miniredis/v2/LICENSE new file mode 100644 index 000000000..bb02657ca --- /dev/null +++ b/LICENSES/github.com/alicebob/miniredis/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Harmen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/github.com/alicebob/miniredis/v2/fpconv/LICENSE.txt b/LICENSES/github.com/alicebob/miniredis/v2/fpconv/LICENSE.txt new file mode 100644 index 000000000..0a0af2e8f --- /dev/null +++ b/LICENSES/github.com/alicebob/miniredis/v2/fpconv/LICENSE.txt @@ -0,0 +1,26 @@ +This code is derived from the C code in redis-7.2.0/deps/fpconv/*, which has +this license: + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/alicebob/miniredis/v2/geohash/LICENSE b/LICENSES/github.com/alicebob/miniredis/v2/geohash/LICENSE new file mode 100644 index 000000000..c0190c9a6 --- /dev/null +++ b/LICENSES/github.com/alicebob/miniredis/v2/geohash/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Michael McLoughlin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/LICENSES/github.com/alicebob/miniredis/v2/gopher-json/LICENSE b/LICENSES/github.com/alicebob/miniredis/v2/gopher-json/LICENSE new file mode 100644 index 000000000..68a49daad --- /dev/null +++ b/LICENSES/github.com/alicebob/miniredis/v2/gopher-json/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/LICENSES/github.com/alicebob/miniredis/v2/hyperloglog/LICENSE b/LICENSES/github.com/alicebob/miniredis/v2/hyperloglog/LICENSE new file mode 100644 index 000000000..8436fdb43 --- /dev/null +++ b/LICENSES/github.com/alicebob/miniredis/v2/hyperloglog/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Axiom Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/github.com/alicebob/miniredis/v2/metro/LICENSE b/LICENSES/github.com/alicebob/miniredis/v2/metro/LICENSE new file mode 100644 index 000000000..6243b617c --- /dev/null +++ b/LICENSES/github.com/alicebob/miniredis/v2/metro/LICENSE @@ -0,0 +1,24 @@ +This package is a mechanical translation of the reference C++ code for +MetroHash, available at https://github.com/jandrewrogers/MetroHash + +The MIT License (MIT) + +Copyright (c) 2016 Damian Gryski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/NOTICE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/NOTICE.txt new file mode 100644 index 000000000..899129ecc --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/NOTICE.txt @@ -0,0 +1,3 @@ +AWS SDK for Go +Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2014-2015 Stripe, Inc. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/config/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/config/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/config/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/credentials/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/credentials/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/credentials/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/feature/ec2/imds/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/internal/configsources/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/configsources/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/configsources/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/LICENSE b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/LICENSE new file mode 100644 index 000000000..fe6a62006 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/internal/v4a/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/v4a/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/internal/v4a/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/checksum/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/checksum/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/checksum/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/s3/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/s3/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/s3/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/signin/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/signin/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/signin/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/sso/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/sso/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/sso/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/ssooidc/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/ssooidc/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/ssooidc/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/aws-sdk-go-v2/service/sts/LICENSE.txt b/LICENSES/github.com/aws/aws-sdk-go-v2/service/sts/LICENSE.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/aws/aws-sdk-go-v2/service/sts/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/aws/smithy-go/LICENSE b/LICENSES/github.com/aws/smithy-go/LICENSE new file mode 100644 index 000000000..67db85882 --- /dev/null +++ b/LICENSES/github.com/aws/smithy-go/LICENSE @@ -0,0 +1,175 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/LICENSES/github.com/aws/smithy-go/NOTICE b/LICENSES/github.com/aws/smithy-go/NOTICE new file mode 100644 index 000000000..616fc5889 --- /dev/null +++ b/LICENSES/github.com/aws/smithy-go/NOTICE @@ -0,0 +1 @@ +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/LICENSES/github.com/aws/smithy-go/internal/sync/singleflight/LICENSE b/LICENSES/github.com/aws/smithy-go/internal/sync/singleflight/LICENSE new file mode 100644 index 000000000..fe6a62006 --- /dev/null +++ b/LICENSES/github.com/aws/smithy-go/internal/sync/singleflight/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/LICENSES/github.com/beorn7/perks/quantile/LICENSE b/LICENSES/github.com/beorn7/perks/quantile/LICENSE new file mode 100644 index 000000000..339177be6 --- /dev/null +++ b/LICENSES/github.com/beorn7/perks/quantile/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013 Blake Mizerany + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/cenkalti/backoff/v5/LICENSE b/LICENSES/github.com/cenkalti/backoff/v5/LICENSE new file mode 100644 index 000000000..89b817996 --- /dev/null +++ b/LICENSES/github.com/cenkalti/backoff/v5/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Cenk Altı + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/cespare/xxhash/v2/LICENSE.txt b/LICENSES/github.com/cespare/xxhash/v2/LICENSE.txt new file mode 100644 index 000000000..24b53065f --- /dev/null +++ b/LICENSES/github.com/cespare/xxhash/v2/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2016 Caleb Spare + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/cncf/xds/go/LICENSE b/LICENSES/github.com/cncf/xds/go/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/cncf/xds/go/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/containerd/stargz-snapshotter/estargz/LICENSE b/LICENSES/github.com/containerd/stargz-snapshotter/estargz/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/containerd/stargz-snapshotter/estargz/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/davecgh/go-spew/spew/LICENSE b/LICENSES/github.com/davecgh/go-spew/spew/LICENSE new file mode 100644 index 000000000..bc52e96f2 --- /dev/null +++ b/LICENSES/github.com/davecgh/go-spew/spew/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012-2016 Dave Collins + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/LICENSES/github.com/dgryski/go-rendezvous/LICENSE b/LICENSES/github.com/dgryski/go-rendezvous/LICENSE new file mode 100644 index 000000000..22080f736 --- /dev/null +++ b/LICENSES/github.com/dgryski/go-rendezvous/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017-2020 Damian Gryski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSES/github.com/docker/cli/cli/config/LICENSE b/LICENSES/github.com/docker/cli/cli/config/LICENSE new file mode 100644 index 000000000..9c8e20ab8 --- /dev/null +++ b/LICENSES/github.com/docker/cli/cli/config/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2013-2017 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/docker/cli/cli/config/NOTICE b/LICENSES/github.com/docker/cli/cli/config/NOTICE new file mode 100644 index 000000000..1c40faaec --- /dev/null +++ b/LICENSES/github.com/docker/cli/cli/config/NOTICE @@ -0,0 +1,19 @@ +Docker +Copyright 2012-2017 Docker, Inc. + +This product includes software developed at Docker, Inc. (https://www.docker.com). + +This product contains software (https://github.com/creack/pty) developed +by Keith Rarick, licensed under the MIT License. + +The following is courtesy of our legal counsel: + + +Use and transfer of Docker may be subject to certain restrictions by the +United States and other governments. +It is your responsibility to ensure that your use and/or transfer does not +violate applicable laws. + +For more information, see https://www.bis.doc.gov + +See also https://www.apache.org/dev/crypto.html and/or seek legal counsel. diff --git a/LICENSES/github.com/docker/docker-credential-helpers/LICENSE b/LICENSES/github.com/docker/docker-credential-helpers/LICENSE new file mode 100644 index 000000000..1ea555e2a --- /dev/null +++ b/LICENSES/github.com/docker/docker-credential-helpers/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2016 David Calavera + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/emicklei/go-restful/v3/LICENSE b/LICENSES/github.com/emicklei/go-restful/v3/LICENSE new file mode 100644 index 000000000..ece7ec61e --- /dev/null +++ b/LICENSES/github.com/emicklei/go-restful/v3/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012,2013 Ernest Micklei + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/LICENSES/github.com/envoyproxy/go-control-plane/envoy/LICENSE b/LICENSES/github.com/envoyproxy/go-control-plane/envoy/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/github.com/envoyproxy/go-control-plane/envoy/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/envoyproxy/go-control-plane/pkg/LICENSE b/LICENSES/github.com/envoyproxy/go-control-plane/pkg/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/github.com/envoyproxy/go-control-plane/pkg/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/envoyproxy/go-control-plane/ratelimit/service/ratelimit/v3/LICENSE b/LICENSES/github.com/envoyproxy/go-control-plane/ratelimit/service/ratelimit/v3/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/github.com/envoyproxy/go-control-plane/ratelimit/service/ratelimit/v3/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/envoyproxy/protoc-gen-validate/validate/LICENSE b/LICENSES/github.com/envoyproxy/protoc-gen-validate/validate/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/envoyproxy/protoc-gen-validate/validate/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/evanphx/json-patch/v5/LICENSE b/LICENSES/github.com/evanphx/json-patch/v5/LICENSE new file mode 100644 index 000000000..df76d7d77 --- /dev/null +++ b/LICENSES/github.com/evanphx/json-patch/v5/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2014, Evan Phoenix +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the Evan Phoenix nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/felixge/httpsnoop/LICENSE.txt b/LICENSES/github.com/felixge/httpsnoop/LICENSE.txt new file mode 100644 index 000000000..e028b46a9 --- /dev/null +++ b/LICENSES/github.com/felixge/httpsnoop/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2016 Felix Geisendörfer (felix@debuggable.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/LICENSES/github.com/fsnotify/fsnotify/LICENSE b/LICENSES/github.com/fsnotify/fsnotify/LICENSE new file mode 100644 index 000000000..fb03ade75 --- /dev/null +++ b/LICENSES/github.com/fsnotify/fsnotify/LICENSE @@ -0,0 +1,25 @@ +Copyright © 2012 The Go Authors. All rights reserved. +Copyright © fsnotify Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/fxamacker/cbor/v2/LICENSE b/LICENSES/github.com/fxamacker/cbor/v2/LICENSE new file mode 100644 index 000000000..eaa850492 --- /dev/null +++ b/LICENSES/github.com/fxamacker/cbor/v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-present Faye Amacker + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/LICENSES/github.com/go-jose/go-jose/v4/LICENSE b/LICENSES/github.com/go-jose/go-jose/v4/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-jose/go-jose/v4/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-jose/go-jose/v4/json/LICENSE b/LICENSES/github.com/go-jose/go-jose/v4/json/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/LICENSES/github.com/go-jose/go-jose/v4/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/go-logr/logr/LICENSE b/LICENSES/github.com/go-logr/logr/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/github.com/go-logr/logr/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-logr/stdr/LICENSE b/LICENSES/github.com/go-logr/stdr/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/go-logr/stdr/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-logr/zapr/LICENSE b/LICENSES/github.com/go-logr/zapr/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/github.com/go-logr/zapr/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/jsonpointer/LICENSE b/LICENSES/github.com/go-openapi/jsonpointer/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/go-openapi/jsonpointer/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/jsonpointer/NOTICE b/LICENSES/github.com/go-openapi/jsonpointer/NOTICE new file mode 100644 index 000000000..f3b51939a --- /dev/null +++ b/LICENSES/github.com/go-openapi/jsonpointer/NOTICE @@ -0,0 +1,39 @@ +Copyright 2015-2025 go-swagger maintainers + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +This software library, github.com/go-openapi/jsonpointer, includes software developed +by the go-swagger and go-openapi maintainers ("go-swagger maintainers"). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this software except in compliance with the License. + +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0. + +This software is copied from, derived from, and inspired by other original software products. +It ships with copies of other software which license terms are recalled below. + +The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). + +github.com/sigh-399/jsonpointer +=========================== + +// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) +// SPDX-License-Identifier: Apache-2.0 + +Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/github.com/go-openapi/jsonreference/LICENSE b/LICENSES/github.com/go-openapi/jsonreference/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/jsonreference/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/jsonreference/NOTICE b/LICENSES/github.com/go-openapi/jsonreference/NOTICE new file mode 100644 index 000000000..f3b51939a --- /dev/null +++ b/LICENSES/github.com/go-openapi/jsonreference/NOTICE @@ -0,0 +1,39 @@ +Copyright 2015-2025 go-swagger maintainers + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +This software library, github.com/go-openapi/jsonpointer, includes software developed +by the go-swagger and go-openapi maintainers ("go-swagger maintainers"). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this software except in compliance with the License. + +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0. + +This software is copied from, derived from, and inspired by other original software products. +It ships with copies of other software which license terms are recalled below. + +The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). + +github.com/sigh-399/jsonpointer +=========================== + +// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) +// SPDX-License-Identifier: Apache-2.0 + +Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/LICENSE b/LICENSES/github.com/go-openapi/swag/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/cmdutils/LICENSE b/LICENSES/github.com/go-openapi/swag/cmdutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/cmdutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/conv/LICENSE b/LICENSES/github.com/go-openapi/swag/conv/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/conv/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/fileutils/LICENSE b/LICENSES/github.com/go-openapi/swag/fileutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/fileutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/jsonname/LICENSE b/LICENSES/github.com/go-openapi/swag/jsonname/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/jsonname/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/jsonutils/LICENSE b/LICENSES/github.com/go-openapi/swag/jsonutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/jsonutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/loading/LICENSE b/LICENSES/github.com/go-openapi/swag/loading/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/loading/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/mangling/LICENSE b/LICENSES/github.com/go-openapi/swag/mangling/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/mangling/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/netutils/LICENSE b/LICENSES/github.com/go-openapi/swag/netutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/netutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/stringutils/LICENSE b/LICENSES/github.com/go-openapi/swag/stringutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/stringutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/typeutils/LICENSE b/LICENSES/github.com/go-openapi/swag/typeutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/typeutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/go-openapi/swag/yamlutils/LICENSE b/LICENSES/github.com/go-openapi/swag/yamlutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/go-openapi/swag/yamlutils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/google/btree/LICENSE b/LICENSES/github.com/google/btree/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/google/btree/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/google/gnostic-models/LICENSE b/LICENSES/github.com/google/gnostic-models/LICENSE new file mode 100644 index 000000000..6b0b1270f --- /dev/null +++ b/LICENSES/github.com/google/gnostic-models/LICENSE @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/LICENSES/github.com/google/go-cmp/cmp/LICENSE b/LICENSES/github.com/google/go-cmp/cmp/LICENSE new file mode 100644 index 000000000..32017f8fa --- /dev/null +++ b/LICENSES/github.com/google/go-cmp/cmp/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2017 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/google/go-containerregistry/LICENSE b/LICENSES/github.com/google/go-containerregistry/LICENSE new file mode 100644 index 000000000..7a4a3ea24 --- /dev/null +++ b/LICENSES/github.com/google/go-containerregistry/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/LICENSES/github.com/google/s2a-go/LICENSE.md b/LICENSES/github.com/google/s2a-go/LICENSE.md new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/google/s2a-go/LICENSE.md @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/google/uuid/LICENSE b/LICENSES/github.com/google/uuid/LICENSE new file mode 100644 index 000000000..5dc68268d --- /dev/null +++ b/LICENSES/github.com/google/uuid/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009,2014 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/googleapis/enterprise-certificate-proxy/client/LICENSE b/LICENSES/github.com/googleapis/enterprise-certificate-proxy/client/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/googleapis/enterprise-certificate-proxy/client/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/googleapis/gax-go/v2/LICENSE b/LICENSES/github.com/googleapis/gax-go/v2/LICENSE new file mode 100644 index 000000000..6d16b6578 --- /dev/null +++ b/LICENSES/github.com/googleapis/gax-go/v2/LICENSE @@ -0,0 +1,27 @@ +Copyright 2016, Google Inc. +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/gorilla/websocket/LICENSE b/LICENSES/github.com/gorilla/websocket/LICENSE new file mode 100644 index 000000000..9171c9722 --- /dev/null +++ b/LICENSES/github.com/gorilla/websocket/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE b/LICENSES/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE new file mode 100644 index 000000000..364516251 --- /dev/null +++ b/LICENSES/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Gengo, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Gengo, Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/hashicorp/go-reap/.gitignore b/LICENSES/github.com/hashicorp/go-reap/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/LICENSES/github.com/hashicorp/go-reap/LICENSE b/LICENSES/github.com/hashicorp/go-reap/LICENSE new file mode 100644 index 000000000..2911811b7 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/LICENSE @@ -0,0 +1,365 @@ +Copyright IBM Corp. 2015, 2023 + +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. + diff --git a/LICENSES/github.com/hashicorp/go-reap/README.md b/LICENSES/github.com/hashicorp/go-reap/README.md new file mode 100644 index 000000000..92994a697 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/README.md @@ -0,0 +1,46 @@ +# go-reap + +Provides a super simple set of functions for reaping child processes. This is +useful for running applications as PID 1 in a Docker container. + +Note that a mutex is supplied to allow your application to prevent reaping of +child processes during certain periods. You need to use care in order to +prevent the reaper from stealing your return values from uses of packages like +Go's exec. We use an `RWMutex` so that we don't serialize all of your +application's execution of sub processes with each other, but we do serialize +them with reaping. Your application should get a read lock when it wants to do +a wait and be safe from the reaper. + +This should be supported on most UNIX flavors, but is not supported on Windows +or Solaris. Unsupported platforms have a stub implementation that's safe to call, +as well as an API to check if reaping is supported so that you can produce an +error in your application code. + +Documentation +============= + +The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/go-reap). + +Example +======= + +Below is a simple example of usage + +```go +// Reap children with no control or feedback. +go reap.ReapChildren(nil, nil, nil) + +// Get feedback on reaped children and errors. +if reap.IsSupported() { + pids := make(reap.PidCh, 1) + errors := make(reap.ErrorCh, 1) + done := make(chan struct{}) + var reapLock sync.RWMutex + go reap.ReapChildren(pids, errors, done, &reapLock) + // ... + close(done) +} else { + fmt.Println("Sorry, go-reap isn't supported on your platform.") +} +``` + diff --git a/LICENSES/github.com/hashicorp/go-reap/reap.go b/LICENSES/github.com/hashicorp/go-reap/reap.go new file mode 100644 index 000000000..329a421e7 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/reap.go @@ -0,0 +1,8 @@ +package reap + +// ErrorCh is an error channel that lets you know when an error was +// encountered while reaping child processes. +type ErrorCh chan error + +// PidCh returns the process IDs of reaped child processes. +type PidCh chan int diff --git a/LICENSES/github.com/hashicorp/go-reap/reap_stub.go b/LICENSES/github.com/hashicorp/go-reap/reap_stub.go new file mode 100644 index 000000000..4dc526593 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/reap_stub.go @@ -0,0 +1,17 @@ +// +build windows solaris + +package reap + +import ( + "sync" +) + +// IsSupported returns true if child process reaping is supported on this +// platform. This version always returns false. +func IsSupported() bool { + return false +} + +// ReapChildren is not supported so this always returns right away. +func ReapChildren(pids PidCh, errors ErrorCh, done chan struct{}, reapLock *sync.RWMutex) { +} diff --git a/LICENSES/github.com/hashicorp/go-reap/reap_stub_test.go b/LICENSES/github.com/hashicorp/go-reap/reap_stub_test.go new file mode 100644 index 000000000..2008134f6 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/reap_stub_test.go @@ -0,0 +1,27 @@ +// +build windows solaris + +package reap + +import ( + "runtime" + "testing" +) + +func TestReap_IsSupported(t *testing.T) { + if IsSupported() { + t.Fatalf("reap should not be supported on %s", runtime.GOOS) + } +} + +func TestReap_ReapChildren(t *testing.T) { + pids := make(PidCh, 1) + errors := make(ErrorCh, 1) + ReapChildren(pids, errors, nil, nil) + select { + case <-pids: + t.Fatalf("should not report any pids") + case <-errors: + t.Fatalf("should not report any errors") + default: + } +} diff --git a/LICENSES/github.com/hashicorp/go-reap/reap_unix.go b/LICENSES/github.com/hashicorp/go-reap/reap_unix.go new file mode 100644 index 000000000..45d35dba1 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/reap_unix.go @@ -0,0 +1,96 @@ +// +build !windows,!solaris + +package reap + +import ( + "os" + "os/signal" + "sync" + + "golang.org/x/sys/unix" +) + +// IsSupported returns true if child process reaping is supported on this +// platform. +func IsSupported() bool { + return true +} + +// ReapChildren is a long-running routine that blocks waiting for child +// processes to exit and reaps them, reporting reaped process IDs to the +// optional pids channel and any errors to the optional errors channel. +// +// The optional reapLock will be used to prevent reaping during periods +// when you know your application is waiting for subprocesses to return. +// You need to use care in order to prevent the reaper from stealing your +// return values from uses of packages like Go's exec. We use an RWMutex +// so that we don't serialize all of the application's execution of sub +// processes with each other, but we do serialize them with reaping. The +// application should get a read lock when it wants to do a wait. +func ReapChildren(pids PidCh, errors ErrorCh, done chan struct{}, reapLock *sync.RWMutex) { + c := make(chan os.Signal, 1) + signal.Notify(c, unix.SIGCHLD) + + for { + // Block for an incoming signal that a child has exited. + select { + case <-c: + // Got a child signal, drop out and reap. + case <-done: + return + } + + // Attempt to reap all abandoned child processes after getting + // the reap lock, which makes sure the application isn't doing + // any waiting of its own. Note that we do the full write lock + // here. + func() { + if reapLock != nil { + reapLock.Lock() + defer reapLock.Unlock() + } + + POLL: + // Try to reap children until there aren't any more. We + // never block in here so that we are always responsive + // to signals, at the expense of possibly leaving a + // child behind if we get here too quickly. Any + // stragglers should get reaped the next time we see a + // signal, so we won't leak in the long run. + var status unix.WaitStatus + pid, err := unix.Wait4(-1, &status, unix.WNOHANG, nil) + switch err { + case nil: + // Got a child, clean this up and poll again. + if pid > 0 { + if pids != nil { + pids <- pid + } + goto POLL + } + return + + case unix.ECHILD: + // No more children, we are done. + return + + case unix.EINTR: + // We got interrupted, try again. This likely + // can't happen since we are calling Wait4 in a + // non-blocking fashion, but it's good to be + // complete and handle this case rather than + // fail. + goto POLL + + default: + // We got some other error we didn't expect. + // Wait for another SIGCHLD so we don't + // potentially spam in here and chew up CPU. + if errors != nil { + errors <- err + } + return + } + }() + } +} diff --git a/LICENSES/github.com/hashicorp/go-reap/reap_unix_test.go b/LICENSES/github.com/hashicorp/go-reap/reap_unix_test.go new file mode 100644 index 000000000..a77822378 --- /dev/null +++ b/LICENSES/github.com/hashicorp/go-reap/reap_unix_test.go @@ -0,0 +1,129 @@ +// +build !windows,!solaris + +package reap + +import ( + "os" + "os/exec" + "runtime" + "sync" + "testing" + "time" + + "golang.org/x/sys/unix" +) + +func TestReap_IsSupported(t *testing.T) { + if !IsSupported() { + t.Fatalf("reap should be supported on %s", runtime.GOOS) + } +} + +func TestReap_ReapChildren(t *testing.T) { + pids := make(PidCh, 1) + errors := make(ErrorCh, 1) + done := make(chan struct{}, 1) + var reapLock sync.RWMutex + + didExit := make(chan struct{}, 1) + go func() { + ReapChildren(pids, errors, done, &reapLock) + didExit <- struct{}{} + }() + time.Sleep(1 * time.Second) + + killAndCheck := func() { + cmd := exec.Command("sleep", "5") + if err := cmd.Start(); err != nil { + t.Fatalf("err: %v", err) + } + + childPid := cmd.Process.Pid + if err := cmd.Process.Kill(); err != nil { + t.Fatalf("err: %v", err) + } + + select { + case pid := <-pids: + if pid != childPid { + t.Fatalf("unexpected pid: %d != %d", pid, childPid) + } + case err := <-errors: + t.Fatalf("err: %v", err) + case <-time.After(1 * time.Second): + t.Fatalf("should have reaped %d", childPid) + } + } + + // Kill a child process and make sure it gets detected. + killAndCheck() + + // Fire off a subprocess. + cmd := exec.Command("sleep", "5") + if err := cmd.Start(); err != nil { + t.Fatalf("err: %v", err) + } + + // Send a spurious SIGCHLD. + if err := unix.Kill(os.Getpid(), unix.SIGCHLD); err != nil { + t.Fatalf("err: %v", err) + } + + // Make sure the reaper didn't report anything. + select { + case pid := <-pids: + t.Fatalf("unexpected pid: %d", pid) + case err := <-errors: + t.Fatalf("err: %v", err) + case <-time.After(1 * time.Second): + // Good - nothing was sent to the channels. + } + + // Take the reap lock. + reapLock.RLock() + + // Now kill the child subprocess. + childPid := cmd.Process.Pid + if err := cmd.Process.Kill(); err != nil { + t.Fatalf("err: %v", err) + } + + // Make sure the reaper didn't report anything. + select { + case pid := <-pids: + t.Fatalf("unexpected pid: %d", pid) + case err := <-errors: + t.Fatalf("err: %v", err) + case <-time.After(1 * time.Second): + // Good - nothing was sent to the channels. + } + + // Give up the reap lock. + reapLock.RUnlock() + + // Make sure the reaper sees it. + select { + case pid := <-pids: + if pid != childPid { + t.Fatalf("unexpected pid: %d != %d", pid, childPid) + } + case err := <-errors: + t.Fatalf("err: %v", err) + case <-time.After(1 * time.Second): + t.Fatalf("should have reaped %d", childPid) + } + + // Run a few more cycles to make sure things work. + killAndCheck() + killAndCheck() + killAndCheck() + + // Shut it down. + close(done) + select { + case <-didExit: + // Good - the goroutine shut down. + case <-time.After(1 * time.Second): + t.Fatalf("should have shut down") + } +} diff --git a/LICENSES/github.com/json-iterator/go/LICENSE b/LICENSES/github.com/json-iterator/go/LICENSE new file mode 100644 index 000000000..2cf4f5ab2 --- /dev/null +++ b/LICENSES/github.com/json-iterator/go/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 json-iterator + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/github.com/klauspost/compress/LICENSE b/LICENSES/github.com/klauspost/compress/LICENSE new file mode 100644 index 000000000..87d557477 --- /dev/null +++ b/LICENSES/github.com/klauspost/compress/LICENSE @@ -0,0 +1,304 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2019 Klaus Post. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------ + +Files: gzhttp/* + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016-2017 The New York Times Company + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +------------------ + +Files: s2/cmd/internal/readahead/* + +The MIT License (MIT) + +Copyright (c) 2015 Klaus Post + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------- +Files: snappy/* +Files: internal/snapref/* + +Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----------------- + +Files: s2/cmd/internal/filepathx/* + +Copyright 2016 The filepathx Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/klauspost/compress/internal/snapref/LICENSE b/LICENSES/github.com/klauspost/compress/internal/snapref/LICENSE new file mode 100644 index 000000000..6050c10f4 --- /dev/null +++ b/LICENSES/github.com/klauspost/compress/internal/snapref/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt b/LICENSES/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt new file mode 100644 index 000000000..24b53065f --- /dev/null +++ b/LICENSES/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2016 Caleb Spare + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/github.com/mitchellh/go-homedir/LICENSE b/LICENSES/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/LICENSES/github.com/mitchellh/go-homedir/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSES/github.com/moby/spdystream/LICENSE b/LICENSES/github.com/moby/spdystream/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/github.com/moby/spdystream/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/moby/spdystream/NOTICE b/LICENSES/github.com/moby/spdystream/NOTICE new file mode 100644 index 000000000..24e2e2aa3 --- /dev/null +++ b/LICENSES/github.com/moby/spdystream/NOTICE @@ -0,0 +1,17 @@ +SpdyStream +Copyright 2014-2021 Docker Inc. + +This product includes software developed at +Docker Inc. (https://www.docker.com/). + +SPDY implementation (spdy/) + +The spdy directory contains code derived from the Go project (golang.org/x/net). + +Copyright 2009-2013 The Go Authors. +Licensed under the BSD 3-Clause License. + +Modifications Copyright 2014-2021 Docker Inc. + +The BSD license text and Go patent grant are included in +spdy/LICENSE and spdy/PATENTS. diff --git a/LICENSES/github.com/moby/spdystream/spdy/LICENSE b/LICENSES/github.com/moby/spdystream/spdy/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/LICENSES/github.com/moby/spdystream/spdy/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/modern-go/concurrent/LICENSE b/LICENSES/github.com/modern-go/concurrent/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/modern-go/concurrent/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/modern-go/reflect2/LICENSE b/LICENSES/github.com/modern-go/reflect2/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/modern-go/reflect2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/munnerz/goautoneg/LICENSE b/LICENSES/github.com/munnerz/goautoneg/LICENSE new file mode 100644 index 000000000..bbc7b897c --- /dev/null +++ b/LICENSES/github.com/munnerz/goautoneg/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2011, Open Knowledge Foundation Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + Neither the name of the Open Knowledge Foundation Ltd. nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/opencontainers/go-digest/LICENSE b/LICENSES/github.com/opencontainers/go-digest/LICENSE new file mode 100644 index 000000000..3ac8ab648 --- /dev/null +++ b/LICENSES/github.com/opencontainers/go-digest/LICENSE @@ -0,0 +1,192 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2019, 2020 OCI Contributors + Copyright 2016 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/opencontainers/image-spec/specs-go/LICENSE b/LICENSES/github.com/opencontainers/image-spec/specs-go/LICENSE new file mode 100644 index 000000000..9fdc20fdb --- /dev/null +++ b/LICENSES/github.com/opencontainers/image-spec/specs-go/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2016 The Linux Foundation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/opencontainers/runtime-spec/specs-go/LICENSE b/LICENSES/github.com/opencontainers/runtime-spec/specs-go/LICENSE new file mode 100644 index 000000000..bdc403653 --- /dev/null +++ b/LICENSES/github.com/opencontainers/runtime-spec/specs-go/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015 The Linux Foundation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/pmezard/go-difflib/difflib/LICENSE b/LICENSES/github.com/pmezard/go-difflib/difflib/LICENSE new file mode 100644 index 000000000..c67dad612 --- /dev/null +++ b/LICENSES/github.com/pmezard/go-difflib/difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/LICENSE b/LICENSES/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/LICENSE new file mode 100644 index 000000000..65d761bc9 --- /dev/null +++ b/LICENSES/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/prometheus/client_golang/prometheus/LICENSE b/LICENSES/github.com/prometheus/client_golang/prometheus/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/prometheus/client_golang/prometheus/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/prometheus/client_golang/prometheus/NOTICE b/LICENSES/github.com/prometheus/client_golang/prometheus/NOTICE new file mode 100644 index 000000000..b9cc55abb --- /dev/null +++ b/LICENSES/github.com/prometheus/client_golang/prometheus/NOTICE @@ -0,0 +1,18 @@ +Prometheus instrumentation library for Go applications +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). + + +The following components are included in this product: + +perks - a fork of https://github.com/bmizerany/perks +https://github.com/beorn7/perks +Copyright 2013-2015 Blake Mizerany, Björn Rabenstein +See https://github.com/beorn7/perks/blob/master/README.md for license details. + +Go support for Protocol Buffers - Google's data interchange format +http://github.com/golang/protobuf/ +Copyright 2010 The Go Authors +See source code for license details. diff --git a/LICENSES/github.com/prometheus/client_model/go/LICENSE b/LICENSES/github.com/prometheus/client_model/go/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/prometheus/client_model/go/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/prometheus/client_model/go/NOTICE b/LICENSES/github.com/prometheus/client_model/go/NOTICE new file mode 100644 index 000000000..20110e410 --- /dev/null +++ b/LICENSES/github.com/prometheus/client_model/go/NOTICE @@ -0,0 +1,5 @@ +Data model artifacts for Prometheus. +Copyright 2012-2015 The Prometheus Authors + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). diff --git a/LICENSES/github.com/prometheus/common/LICENSE b/LICENSES/github.com/prometheus/common/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/prometheus/common/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/prometheus/common/NOTICE b/LICENSES/github.com/prometheus/common/NOTICE new file mode 100644 index 000000000..636a2c1a5 --- /dev/null +++ b/LICENSES/github.com/prometheus/common/NOTICE @@ -0,0 +1,5 @@ +Common libraries shared by Prometheus Go components. +Copyright 2015 The Prometheus Authors + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). diff --git a/LICENSES/github.com/prometheus/otlptranslator/LICENSE b/LICENSES/github.com/prometheus/otlptranslator/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/prometheus/otlptranslator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/prometheus/procfs/LICENSE b/LICENSES/github.com/prometheus/procfs/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/prometheus/procfs/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/prometheus/procfs/NOTICE b/LICENSES/github.com/prometheus/procfs/NOTICE new file mode 100644 index 000000000..53c5e9aa1 --- /dev/null +++ b/LICENSES/github.com/prometheus/procfs/NOTICE @@ -0,0 +1,7 @@ +procfs provides functions to retrieve system, kernel and process +metrics from the pseudo-filesystem proc. + +Copyright 2014-2015 The Prometheus Authors + +This product includes software developed at +SoundCloud Ltd. (http://soundcloud.com/). diff --git a/LICENSES/github.com/redis/go-redis/v9/LICENSE b/LICENSES/github.com/redis/go-redis/v9/LICENSE new file mode 100644 index 000000000..f4967dbc5 --- /dev/null +++ b/LICENSES/github.com/redis/go-redis/v9/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2013 The github.com/redis/go-redis Authors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/sirupsen/logrus/LICENSE b/LICENSES/github.com/sirupsen/logrus/LICENSE new file mode 100644 index 000000000..f090cb42f --- /dev/null +++ b/LICENSES/github.com/sirupsen/logrus/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Simon Eskildsen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSES/github.com/spf13/cobra/LICENSE.txt b/LICENSES/github.com/spf13/cobra/LICENSE.txt new file mode 100644 index 000000000..298f0e266 --- /dev/null +++ b/LICENSES/github.com/spf13/cobra/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/LICENSES/github.com/spf13/pflag/LICENSE b/LICENSES/github.com/spf13/pflag/LICENSE new file mode 100644 index 000000000..63ed1cfea --- /dev/null +++ b/LICENSES/github.com/spf13/pflag/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 Alex Ogier. All rights reserved. +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/spiffe/go-spiffe/v2/LICENSE b/LICENSES/github.com/spiffe/go-spiffe/v2/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/github.com/spiffe/go-spiffe/v2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/vbatts/tar-split/archive/tar/LICENSE b/LICENSES/github.com/vbatts/tar-split/archive/tar/LICENSE new file mode 100644 index 000000000..ca03685b1 --- /dev/null +++ b/LICENSES/github.com/vbatts/tar-split/archive/tar/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2015 Vincent Batts, Raleigh, NC, USA + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/github.com/vishvananda/netlink/LICENSE b/LICENSES/github.com/vishvananda/netlink/LICENSE new file mode 100644 index 000000000..9f64db858 --- /dev/null +++ b/LICENSES/github.com/vishvananda/netlink/LICENSE @@ -0,0 +1,192 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/vishvananda/netns/LICENSE b/LICENSES/github.com/vishvananda/netns/LICENSE new file mode 100644 index 000000000..9f64db858 --- /dev/null +++ b/LICENSES/github.com/vishvananda/netns/LICENSE @@ -0,0 +1,192 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2014 Vishvananda Ishaya. + Copyright 2014 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/github.com/x448/float16/LICENSE b/LICENSES/github.com/x448/float16/LICENSE new file mode 100644 index 000000000..bf6e35785 --- /dev/null +++ b/LICENSES/github.com/x448/float16/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2019 Montgomery Edwards⁴⁴⁸ and Faye Amacker + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/LICENSES/github.com/yuin/gopher-lua/LICENSE b/LICENSES/github.com/yuin/gopher-lua/LICENSE new file mode 100644 index 000000000..4daf480a2 --- /dev/null +++ b/LICENSES/github.com/yuin/gopher-lua/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Yusuke Inuzuka + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/go.opentelemetry.io/auto/sdk/LICENSE b/LICENSES/go.opentelemetry.io/auto/sdk/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/auto/sdk/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/go.opentelemetry.io/contrib/detectors/gcp/LICENSE b/LICENSES/go.opentelemetry.io/contrib/detectors/gcp/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/contrib/detectors/gcp/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE b/LICENSES/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/LICENSE b/LICENSES/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/LICENSE b/LICENSES/go.opentelemetry.io/otel/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/LICENSE b/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/LICENSE b/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/LICENSE b/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/exporters/prometheus/LICENSE b/LICENSES/go.opentelemetry.io/otel/exporters/prometheus/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/exporters/prometheus/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/metric/LICENSE b/LICENSES/go.opentelemetry.io/otel/metric/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/metric/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/sdk/LICENSE b/LICENSES/go.opentelemetry.io/otel/sdk/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/sdk/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/sdk/metric/LICENSE b/LICENSES/go.opentelemetry.io/otel/sdk/metric/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/sdk/metric/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/otel/trace/LICENSE b/LICENSES/go.opentelemetry.io/otel/trace/LICENSE new file mode 100644 index 000000000..f1aee0f11 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/otel/trace/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSES/go.opentelemetry.io/proto/otlp/LICENSE b/LICENSES/go.opentelemetry.io/proto/otlp/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSES/go.opentelemetry.io/proto/otlp/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/go.uber.org/atomic/LICENSE.txt b/LICENSES/go.uber.org/atomic/LICENSE.txt new file mode 100644 index 000000000..8765c9fbc --- /dev/null +++ b/LICENSES/go.uber.org/atomic/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2016 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSES/go.uber.org/multierr/LICENSE.txt b/LICENSES/go.uber.org/multierr/LICENSE.txt new file mode 100644 index 000000000..413e30f7c --- /dev/null +++ b/LICENSES/go.uber.org/multierr/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2017-2021 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSES/go.uber.org/zap/LICENSE b/LICENSES/go.uber.org/zap/LICENSE new file mode 100644 index 000000000..3883b9a7e --- /dev/null +++ b/LICENSES/go.uber.org/zap/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016-2024 Uber Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSES/go.yaml.in/yaml/v2/LICENSE b/LICENSES/go.yaml.in/yaml/v2/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/go.yaml.in/yaml/v2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/go.yaml.in/yaml/v2/NOTICE b/LICENSES/go.yaml.in/yaml/v2/NOTICE new file mode 100644 index 000000000..866d74a7a --- /dev/null +++ b/LICENSES/go.yaml.in/yaml/v2/NOTICE @@ -0,0 +1,13 @@ +Copyright 2011-2016 Canonical Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/go.yaml.in/yaml/v3/LICENSE b/LICENSES/go.yaml.in/yaml/v3/LICENSE new file mode 100644 index 000000000..2683e4bb1 --- /dev/null +++ b/LICENSES/go.yaml.in/yaml/v3/LICENSE @@ -0,0 +1,50 @@ + +This project is covered by two different licenses: MIT and Apache. + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/go.yaml.in/yaml/v3/NOTICE b/LICENSES/go.yaml.in/yaml/v3/NOTICE new file mode 100644 index 000000000..866d74a7a --- /dev/null +++ b/LICENSES/go.yaml.in/yaml/v3/NOTICE @@ -0,0 +1,13 @@ +Copyright 2011-2016 Canonical Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/golang.org/x/crypto/LICENSE b/LICENSES/golang.org/x/crypto/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/crypto/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/net/LICENSE b/LICENSES/golang.org/x/net/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/net/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/oauth2/LICENSE b/LICENSES/golang.org/x/oauth2/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/oauth2/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/sync/LICENSE b/LICENSES/golang.org/x/sync/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/sync/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/sys/LICENSE b/LICENSES/golang.org/x/sys/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/sys/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/sys/unix/LICENSE b/LICENSES/golang.org/x/sys/unix/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/sys/unix/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/term/LICENSE b/LICENSES/golang.org/x/term/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/term/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/text/LICENSE b/LICENSES/golang.org/x/text/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/text/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/golang.org/x/time/rate/LICENSE b/LICENSES/golang.org/x/time/rate/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/LICENSES/golang.org/x/time/rate/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/gomodules.xyz/jsonpatch/v2/LICENSE b/LICENSES/gomodules.xyz/jsonpatch/v2/LICENSE new file mode 100644 index 000000000..8f71f43fe --- /dev/null +++ b/LICENSES/gomodules.xyz/jsonpatch/v2/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/LICENSES/google.golang.org/api/LICENSE b/LICENSES/google.golang.org/api/LICENSE new file mode 100644 index 000000000..263aa7a0c --- /dev/null +++ b/LICENSES/google.golang.org/api/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/google.golang.org/api/internal/third_party/uritemplates/LICENSE b/LICENSES/google.golang.org/api/internal/third_party/uritemplates/LICENSE new file mode 100644 index 000000000..7109c6ef9 --- /dev/null +++ b/LICENSES/google.golang.org/api/internal/third_party/uritemplates/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Joshua Tacoma. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/google.golang.org/genproto/googleapis/api/LICENSE b/LICENSES/google.golang.org/genproto/googleapis/api/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/google.golang.org/genproto/googleapis/api/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/google.golang.org/genproto/googleapis/rpc/LICENSE b/LICENSES/google.golang.org/genproto/googleapis/rpc/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/google.golang.org/genproto/googleapis/rpc/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/google.golang.org/genproto/googleapis/type/LICENSE b/LICENSES/google.golang.org/genproto/googleapis/type/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/google.golang.org/genproto/googleapis/type/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/google.golang.org/grpc/LICENSE b/LICENSES/google.golang.org/grpc/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/google.golang.org/grpc/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/google.golang.org/grpc/NOTICE.txt b/LICENSES/google.golang.org/grpc/NOTICE.txt new file mode 100644 index 000000000..530197749 --- /dev/null +++ b/LICENSES/google.golang.org/grpc/NOTICE.txt @@ -0,0 +1,13 @@ +Copyright 2014 gRPC authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/google.golang.org/protobuf/LICENSE b/LICENSES/google.golang.org/protobuf/LICENSE new file mode 100644 index 000000000..49ea0f928 --- /dev/null +++ b/LICENSES/google.golang.org/protobuf/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2018 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/gopkg.in/evanphx/json-patch.v4/LICENSE b/LICENSES/gopkg.in/evanphx/json-patch.v4/LICENSE new file mode 100644 index 000000000..df76d7d77 --- /dev/null +++ b/LICENSES/gopkg.in/evanphx/json-patch.v4/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2014, Evan Phoenix +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of the Evan Phoenix nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/gopkg.in/inf.v0/LICENSE b/LICENSES/gopkg.in/inf.v0/LICENSE new file mode 100644 index 000000000..87a5cede3 --- /dev/null +++ b/LICENSES/gopkg.in/inf.v0/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go +Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/k8s.io/api/LICENSE b/LICENSES/k8s.io/api/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/api/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/apiextensions-apiserver/pkg/LICENSE b/LICENSES/k8s.io/apiextensions-apiserver/pkg/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/apiextensions-apiserver/pkg/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/apimachinery/pkg/LICENSE b/LICENSES/k8s.io/apimachinery/pkg/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/apimachinery/pkg/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/apimachinery/third_party/forked/golang/LICENSE b/LICENSES/k8s.io/apimachinery/third_party/forked/golang/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/LICENSES/k8s.io/apimachinery/third_party/forked/golang/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/k8s.io/client-go/LICENSE b/LICENSES/k8s.io/client-go/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/client-go/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/klog/v2/LICENSE b/LICENSES/k8s.io/klog/v2/LICENSE new file mode 100644 index 000000000..37ec93a14 --- /dev/null +++ b/LICENSES/k8s.io/klog/v2/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/kube-openapi/pkg/LICENSE b/LICENSES/k8s.io/kube-openapi/pkg/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/kube-openapi/pkg/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE b/LICENSES/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE new file mode 100644 index 000000000..244127300 --- /dev/null +++ b/LICENSES/k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2020 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/k8s.io/kube-openapi/pkg/validation/spec/LICENSE b/LICENSES/k8s.io/kube-openapi/pkg/validation/spec/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/kube-openapi/pkg/validation/spec/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/streaming/pkg/LICENSE b/LICENSES/k8s.io/streaming/pkg/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/streaming/pkg/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/utils/LICENSE b/LICENSES/k8s.io/utils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSES/k8s.io/utils/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/k8s.io/utils/internal/third_party/forked/golang/LICENSE b/LICENSES/k8s.io/utils/internal/third_party/forked/golang/LICENSE new file mode 100644 index 000000000..744875676 --- /dev/null +++ b/LICENSES/k8s.io/utils/internal/third_party/forked/golang/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/sigs.k8s.io/controller-runtime/LICENSE b/LICENSES/sigs.k8s.io/controller-runtime/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/sigs.k8s.io/controller-runtime/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/sigs.k8s.io/json/LICENSE b/LICENSES/sigs.k8s.io/json/LICENSE new file mode 100644 index 000000000..e5adf7f0c --- /dev/null +++ b/LICENSES/sigs.k8s.io/json/LICENSE @@ -0,0 +1,238 @@ +Files other than internal/golang/* licensed under: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +------------------ + +internal/golang/* files licensed under: + + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/sigs.k8s.io/randfill/LICENSE b/LICENSES/sigs.k8s.io/randfill/LICENSE new file mode 100644 index 000000000..9dd29274c --- /dev/null +++ b/LICENSES/sigs.k8s.io/randfill/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 The gofuzz Authors + Copyright 2025 The Kubernetes Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/sigs.k8s.io/randfill/NOTICE b/LICENSES/sigs.k8s.io/randfill/NOTICE new file mode 100644 index 000000000..6984e71f6 --- /dev/null +++ b/LICENSES/sigs.k8s.io/randfill/NOTICE @@ -0,0 +1,24 @@ +When donating the randfill project to the CNCF, we could not reach all the +gofuzz contributors to sign the CNCF CLA. As such, according to the CNCF rules +to donate a repository, we must add a NOTICE referencing section 7 of the CLA +with a list of developers who could not be reached. + +`7. Should You wish to submit work that is not Your original creation, You may +submit it to the Foundation separately from any Contribution, identifying the +complete details of its source and of any license or other restriction +(including, but not limited to, related patents, trademarks, and license +agreements) of which you are personally aware, and conspicuously marking the +work as "Submitted on behalf of a third-party: [named here]".` + +Submitted on behalf of a third-party: @dnephin (Daniel Nephin) +Submitted on behalf of a third-party: @AlekSi (Alexey Palazhchenko) +Submitted on behalf of a third-party: @bbigras (Bruno Bigras) +Submitted on behalf of a third-party: @samirkut (Samir) +Submitted on behalf of a third-party: @posener (Eyal Posener) +Submitted on behalf of a third-party: @Ashikpaul (Ashik Paul) +Submitted on behalf of a third-party: @kwongtailau (Kwongtai) +Submitted on behalf of a third-party: @ericcornelissen (Eric Cornelissen) +Submitted on behalf of a third-party: @eclipseo (Robert-André Mauchin) +Submitted on behalf of a third-party: @yanzhoupan (Andrew Pan) +Submitted on behalf of a third-party: @STRRL (Zhiqiang ZHOU) +Submitted on behalf of a third-party: @disconnect3d (Disconnect3d) diff --git a/LICENSES/sigs.k8s.io/structured-merge-diff/v6/LICENSE b/LICENSES/sigs.k8s.io/structured-merge-diff/v6/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/LICENSES/sigs.k8s.io/structured-merge-diff/v6/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSES/sigs.k8s.io/yaml/LICENSE b/LICENSES/sigs.k8s.io/yaml/LICENSE new file mode 100644 index 000000000..093d6d3ed --- /dev/null +++ b/LICENSES/sigs.k8s.io/yaml/LICENSE @@ -0,0 +1,306 @@ +The MIT License (MIT) + +Copyright (c) 2014 Sam Ghods + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# The forked go-yaml.v3 library under this project is covered by two +different licenses (MIT and Apache): + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +# The forked go-yaml.v2 library under the project is covered by an +Apache license: + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..b7cf0ff89 --- /dev/null +++ b/Makefile @@ -0,0 +1,79 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Default project ID, can be overridden +PROJECT_ID ?= $(shell echo $${USER}-gke-dev) + +# Ko configuration +export KO_DOCKER_REPO := gcr.io/$(PROJECT_ID)/ate-images + +# Go commands +GO := go +KO := hack/ko.sh + +# Binaries +BINDIR := bin/ +ATECTL := $(BINDIR)/kubectl-ate + +.PHONY: all +all: build + +.PHONY: build +build: build-images build-atectl + +.PHONY: build-images +build-images: + $(KO) build ./cmd/servers/ateapi + $(KO) build ./cmd/servers/atelet + $(KO) build ./cmd/servers/podcertcontroller + $(KO) build ./cmd/servers/atenet + +.PHONY: build-atectl +build-atectl: + $(GO) build -o $(ATECTL) ./cmd/kubectl-ate + +.PHONY: build-atenet +build-atenet: + $(GO) build -o $(BINDIR)/atenet ./cmd/servers/atenet + +.PHONY: build-demos +build-demos: + $(KO) build ./cmd/demos/counter + +.PHONY: test +test: + $(GO) test ./... + +.PHONY: e2e +e2e: build build-demos + hack/run-e2e.sh + +.PHONY: fmt verify-fmt + +# Formats all Go files in the project +fmt: + @./hack/update/gofmt.sh + +# Fails if any Go files are not formatted properly +verify-fmt: + @./hack/verify/gofmt.sh + +.PHONY: verify +verify: test + $(GO) vet ./... + bash hack/verify-all.sh + +.PHONY: clean +clean: + rm -rf $(BINDIR) diff --git a/README.md b/README.md new file mode 100644 index 000000000..1337f40e3 --- /dev/null +++ b/README.md @@ -0,0 +1,188 @@ +# Agent Substrate + +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +NOTE: This is not an officially supported Google product. This project is not +eligible for the [Google Open Source Software Vulnerability Rewards Program](https://bughunters.google.com/open-source-security). + +## What is Agent Substrate? + +Agent substrate is a system built on top of Kubernetes which manages agent-like +workloads to achieve higher scale and efficiency than Kubernetes alone can +offer, with lower latency. It builds on top of Kubernetes features like +Pods and Pod autoscaling, but takes the Kubernetes control-plane out of the +critical path to achieve lower latency. + +It can run on any Kubernetes cluster and does not inhibit “regular” use of +Kubernetes in any way. Kubernetes provides the infrastructure provisioning and +management for all types of workloads, while Agent Substrate provides +agent-specific scheduling and control. + +At its core, Agent Substrate maps a larger set of “actors” (applications such +as agents) onto a smaller set of ready “workers” (Kubernetes Pods), relying on +the fact that agent-like applications tend to be idle most of the time to +achieve heavy multiplexing. It provides functionality to manage an actor’s +lifecycle (e.g. create/destroy, suspend/resume), to assign actors to workers in real +time, and to route incoming traffic to them. + +Agent Substrate is intended to be a low-opinion system. The workloads it +manages don't have to be literal AI agents, but those are the best example of +the kind of applications it is designed for. It is not an SDK for building +agents, but rather a system for running them at scale. + +## Demo + +[![Agent Substrate Demo](https://img.youtube.com/vi/ZEzkCFJkzjY/hq1.jpg)](https://www.youtube.com/watch?v=ZEzkCFJkzjY) + +*Watch the Agent Substrate cluster multiplex ~250 stateful actor sessions across just 8 physical pods.* + +This demo highlights the core developer experience and "Agentic Infrastructure" capabilities of Substrate: + +1. **Instant Session Teleport:** High-performance suspend and resume of actors onto any available worker in the pool with sub-second activation. +2. **State Persistence:** Persistent working memory (volatile RAM) and filesystem state preserved perfectly across hibernation cycles via full-state snapshots. +3. **Agent Swarm Multiplexing:** Demonstrates 30x+ oversubscription by "juggling" a large registry of stateful actors onto a small pool of shared physical pods. + +To reproduce this demo in your own cluster, please refer to the detailed walkthroughs in the **[Counter Demo](demos/counter/README.md)** and **[Secret Agent Demo](demos/agent-secret/README.md)**. + +For more videos and walkthroughs, visit our YouTube channel: **[agent-substrate](https://www.youtube.com/channel/UCN9PPqlTtVxlcpbQ-NWpfZQ)**. + +## Framework Agnostic & Compatibility + +Agent Substrate is designed to be **framework and agent harness agnostic**. Because it manages standard OCI containers at the kernel level (via gVisor), it can host agents built on any stack. + +* **Agent Development Kit (ADK):** Native support for ADK-compatible session identity and persistent working memory. +* **LangChain:** Ideal execution environment for long-running, stateful LangChain agents and sandboxed tool-calling. +* **Claude Code & CodeX:** Support for high-density, stateful coding environments that preserve terminal and filesystem state across sessions. +* **Model Context Protocol (MCP):** Deploy secure, sandboxed MCP servers as Substrate Actors to provide durable tools for any LLM. + +## Status and compatibility + +Agent Substrate is currently in VERY early development. It is not ready for +production use, and the APIs are almost guaranteed to change. We are not +making any guarantees about backward compatibility at this stage, and +everything in this project may be changed. + +## Community + +For announcements, technical discussions, and community support, please join +the **[ate-dev](https://groups.google.com/g/ate-dev)** Google Group. + +## Developing + +Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on contributing to +the project. We welcome contributions of all kinds, but the project is VERY +young. Our immediate focus is on building out the core system and demos, so we +may not be able to review or merge contributions that don't align with those +goals in the near term. + +## Quickstart (Development) + +To quickly set up the complete environment: + +1. Make sure you have [`kind`](https://kind.sigs.k8s.io/), [`kubectl`](https://kubernetes.io/docs/tasks/tools/), and [`docker`](https://www.docker.com/) installed and configured on your dev machine. + +2. Run the following steps: +```shell +# create cluster and local registry +hack/create-kind-cluster.sh + +# install ate, valkey, rustfs +hack/install-ate-kind.sh --deploy-ate-system + +# install counter demo +hack/install-ate-kind.sh --deploy-demo-counter + +# install kubectl-ate +go install ./cmd/kubectl-ate + +# create a counter actor and demo it +kubectl ate create actor my-counter-1 --template ate-demo-counter/counter +kubectl port-forward -n ate-system svc/atenet-router 8000:80 & +curl -X POST -H "Host: my-counter-1.actors.resources.substrate.ate.dev" -i http://localhost:8000/ +``` + +### GKE Quickstart (Development) + +1. Create and configure your environment file: + ```bash + cp hack/ate-dev-env.sh.example .ate-dev-env.sh + + # Edit .ate-dev-env.sh to match your project and preferences, then source it: + source .ate-dev-env.sh + ``` + +2. Enable application-default credentials for gcloud: + ```bash + gcloud auth application-default login --project=${PROJECT_ID} + ``` + +3. Provision the required GCP resources (GKE cluster, Redis, GCS, and IAM bindings): + ```bash + go run ./cmd/setup --all + ``` + +4. Deploy the Agent Substrate system to your cluster (remember to navigate back to root directory of this repo before running the following commands): + ```bash + ./hack/install-ate.sh --deploy-ate-system + ``` + +5. You can then deploy the sample applications. See [demos/counter/README.md](demos/counter/README.md) or [demos/sandbox/README.md](demos/sandbox/README.md) for detailed walkthroughs. + ```bash + ./hack/install-ate.sh --deploy-demo-counter + ``` + +#### Custom Setup and Deployment + +You can run individual setup steps to create GCP resources as needed. See `go run ./cmd/setup --help` for available options. For example: +```bash +go run ./cmd/setup --create-cluster +go run ./cmd/setup --create-gvisor-node-pool +``` + +Similarly, you can deploy or cleanup specific Agent Substrate components using the installation script. See `./hack/install-ate.sh --help` for all options. +```bash +# Re-deploy only ate-apiserver of the ATE system +./hack/install-ate-kind.sh --deploy-ate-apiserver + +# Delete everything (core system and all demos) +./hack/install-ate-kind.sh --delete-all +``` + +#### Tearing down resources + +If you need to delete the resources created by the setup script, you can use the provided script `hack/teardown.sh`. This script will delete resources in the reverse order of creation and handles partial failures gracefully. + +```bash +./hack/teardown.sh --all +``` + +Or run individual teardown steps as needed (see `./hack/teardown.sh` for available options). + +## Demos + +We provide several sample applications demonstrating Agent Substrate's capabilities: + +1. **[Counter Demo](demos/counter/README.md)**: A stateful Go HTTP server demonstrating state preservation across suspends/resumes, and dynamic CRD routing. +2. **[Sandbox Demo (Jetski)](demos/sandbox/README.md)**: A secure, sandboxed execution environment (running Alpine Linux) that allows arbitrary shell execution while preserving filesystem state across sessions. +3. **[Claude Code Multiplex](demos/claude-code-multiplex/README.md)**: Demonstrates oversubscribing physical hardware by multiplexing multiple Claude Code agents onto a limited pool of workers. +4. **[Secret Agent](demos/agent-secret/README.md)**: Highlights Substrate's "Zero-Idle" self-suspension and re-animation of volatile process memory. + +### Documentation & Guides +* [API Configuration Guide](docs/api-guide.md): Detailed reference for configuring WorkerPools, ActorTemplates, Secrets, and Volumes. +* [Full CLI Documentation](cmd/kubectl-ate/README.md): Installation and usage for `kubectl-ate`. +* [Observability Guide](docs/observability.md): Guide to actor logging, metrics, and distributed tracing. + +## Tour + +### Commands + +* `cmd/servers/ateapi`: The core control plane API server exposing gRPC endpoints to manage actor and worker lifecycles. +* `cmd/servers/atelet`: A node-level DaemonSet that supervises physical worker pods, coordinates snapshotting, and manages state transfers. +* `cmd/servers/atecontroller`: A Kubernetes controller that reconciles WorkerPool and ActorTemplate custom resources. +* `cmd/servers/atenet`: A combined networking controller providing DNS, Envoy routing, and proxy sidecars. +* `cmd/servers/ateom-gvisor`: An interior-pod helper running inside sandboxed worker pods to execute `runsc` checkpoint and restore commands. +* `cmd/servers/podcertcontroller`: A "polyfill" that provides Pod Certificate signers that + will eventually ship in upstream Kubernetes (with different names). +* `cmd/kubectl-ate`: A CLI tool for managing Agent Substrate resources. See its [README](cmd/kubectl-ate/README.md). +* `cmd/setup`: A provisioning utility to set up the necessary GCP infrastructure resources (GKE, GCS, IAM). +* `demos/`: Sample applications demonstrating Agent Substrate capabilities. diff --git a/api/v1alpha1/actortemplate_types.go b/api/v1alpha1/actortemplate_types.go new file mode 100644 index 000000000..5106fb5a2 --- /dev/null +++ b/api/v1alpha1/actortemplate_types.go @@ -0,0 +1,176 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type PhaseType string + +// Define your phases as constants +const ( + PhaseInitial PhaseType = "" + PhaseResumeGoldenActor PhaseType = "ResumeGoldenActor" + PhaseWaitGoldenActor PhaseType = "WaitGoldenActor" + PhaseReady PhaseType = "Ready" + PhaseFailed PhaseType = "Failed" +) + +// A single application container that you want to run within a WorkerPool. +type Container struct { + // Name of the container. + // +required + Name string `json:"name"` + + // Image to use for the worker replicas. + Image string `json:"image,omitempty"` + + // Entrypoint array. Not executed within a shell. + // +optional + // +listType=atomic + Command []string `json:"command,omitempty"` + + // List of ports to expose from the container. + Ports []corev1.ContainerPort `json:"ports,omitempty"` + + // Environment variables to set in the worker replicas. + Env []corev1.EnvVar `json:"env,omitempty"` +} + +type SnapshotsConfig struct { + // Location to store snapshots in. + // +required + Location string `json:"location"` +} + +// ActorTemplateSpec defined desired spec of an actor. +type ActorTemplateSpec struct { + // PauseImage is the container to use as the root sandbox container. + // + // Typically, set it to [1] for on-gcp, and [2] for off-gcp + // + // - [1] gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da + // - [2] registry.k8s.io/pause:3.10.2@sha256:f548e0e8e3dc1896ca956272154dde3314e8cc4fde0a57577ee9fa1c63f5baf4 + // + // +required + PauseImage string `json:"pauseImage,omitempty"` + + // Containers is the workload definition. + // + // +optional + Containers []Container `json:"containers,omitempty"` + + // Snapshots configuration for the actor. + // +required + SnapshotsConfig SnapshotsConfig `json:"snapshotsConfig"` + + // Name of the worker pool to use for the actor. + // +required + WorkerPoolRef corev1.ObjectReference `json:"workerPoolRef"` + + // Parameters for fetching the runsc binary to use. + // + // +required + Runsc RunscConfig `json:"runsc,omitempty"` +} + +type GCPAuthenticationConfig struct { +} + +// Authentication configuration for atelet to download static files. +// +// If no members are set, then atelet will use anonymous authentication. +type AuthenticationConfig struct { + // Use GCP application-default credentials. + GCP *GCPAuthenticationConfig `json:"gcp,omitempty"` +} + +type RunscPlatformConfig struct { + // The SHA256 hash of the binary to download. Used both to name the + // downloaded file (for preventing conflicts), and to check the integrity of + // the downloaded file. + // + // +required + SHA256Hash string `json:"sha256Hash,omitempty"` + + // A gs:// URL pointing to a runsc binary that can be downloaded (possibly + // with atelet's credentials). + // + // +required + URL string `json:"url,omitempty"` +} + +type RunscConfig struct { + // Configuration for the amd64 binary. + // + // +optional + AMD64 *RunscPlatformConfig `json:"amd64,omitempty"` + + // Configuration for the arm64 binary. + // + // +optional + ARM64 *RunscPlatformConfig `json:"arm64,omitempty"` + + // How should atelet authenticate to download the runsc binary? + Authentication AuthenticationConfig `json:"authentication,omitempty"` +} + +type ActorTemplateStatus struct { + // Phase of the actor template. + // +optional + Phase PhaseType `json:"phase,omitempty"` + + GoldenActorID string `json:"goldenActorID,omitempty"` + TakeGoldenSnapshotAt metav1.Time `json:"takeGoldenSnapshotAt,omitempty"` + GoldenSnapshot string `json:"goldenSnapshot,omitempty"` + + // conditions defines the status conditions array + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +genclient +// +kubebuilder:object:generate=true +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced,shortName=actortemplate +// +kubebuilder:subresource:status +type ActorTemplate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // spec defines the desired state of ActorTemplate + // +required + Spec ActorTemplateSpec `json:"spec"` + + // status is the observed state of ActorTemplate + // +optional + Status ActorTemplateStatus `json:"status,omitempty"` +} + +// ActorTemplateList contains a list of ActorTemplates. +// +kubebuilder:object:generate=true +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced,shortName=actortemplate +type ActorTemplateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ActorTemplate `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ActorTemplate{}, &ActorTemplateList{}) +} diff --git a/api/v1alpha1/actortemplate_types_test.go b/api/v1alpha1/actortemplate_types_test.go new file mode 100644 index 000000000..217f01031 --- /dev/null +++ b/api/v1alpha1/actortemplate_types_test.go @@ -0,0 +1,51 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestActorTemplateDeepCopy(t *testing.T) { + in := &ActorTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-template", + Namespace: "test-ns", + }, + Spec: ActorTemplateSpec{ + WorkerPoolRef: corev1.ObjectReference{ + Namespace: "test-ns", + Name: "test-pool", + }, + SnapshotsConfig: SnapshotsConfig{ + Location: "gs://test-bucket/test-folder", + }, + }, + Status: ActorTemplateStatus{ + Phase: PhaseReady, + GoldenSnapshot: "gs://test-bucket/test-folder/golden", + }, + } + + out := in.DeepCopy() + + if diff := cmp.Diff(in, out); diff != "" { + t.Errorf("DeepCopy() mismatch (-want +got):\n%s", diff) + } +} diff --git a/api/v1alpha1/gen.go b/api/v1alpha1/gen.go new file mode 100644 index 000000000..935a14381 --- /dev/null +++ b/api/v1alpha1/gen.go @@ -0,0 +1,20 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +//go:generate bash ../../hack/run-tool.sh controller-gen crd:headerFile=../../hack/boilerplate/yaml.txt object:headerFile=../../hack/boilerplate/go.txt paths="./" output:crd:dir="../../manifests/ate-install/generated/" +//go:generate bash ../../hack/run-tool.sh client-gen --go-header-file=../../hack/boilerplate/go.txt --clientset-name versioned --input-base github.com/agent-substrate/substrate --input api/v1alpha1 --output-pkg github.com/agent-substrate/substrate/pkg/client/clientset --output-dir ../../pkg/client/clientset +//go:generate bash ../../hack/run-tool.sh lister-gen --go-header-file=../../hack/boilerplate/go.txt --output-pkg github.com/agent-substrate/substrate/pkg/client/listers --output-dir ../../pkg/client/listers github.com/agent-substrate/substrate/api/v1alpha1 +//go:generate bash ../../hack/run-tool.sh informer-gen --go-header-file=../../hack/boilerplate/go.txt --versioned-clientset-package github.com/agent-substrate/substrate/pkg/client/clientset/versioned --listers-package github.com/agent-substrate/substrate/pkg/client/listers --output-pkg github.com/agent-substrate/substrate/pkg/client/informers --output-dir ../../pkg/client/informers github.com/agent-substrate/substrate/api/v1alpha1 diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go new file mode 100644 index 000000000..23f45e844 --- /dev/null +++ b/api/v1alpha1/groupversion_info.go @@ -0,0 +1,41 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package v1alpha1 contains API Schema definitions for the agents v1alpha1 API group. +// +kubebuilder:object:generate=true +// +groupName=ate.dev +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "ate.dev", Version: "v1alpha1"} + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = GroupVersion + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/api/v1alpha1/workerpool_types.go b/api/v1alpha1/workerpool_types.go new file mode 100644 index 000000000..b0ea7fb5c --- /dev/null +++ b/api/v1alpha1/workerpool_types.go @@ -0,0 +1,67 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type WorkerPoolSpec struct { + // Replicas is the number of worker pods to run. + // +required + Replicas int32 `json:"replicas"` + + // AteomImage is the ateom container image to deploy as workers. + // +required + AteomImage string `json:"ateomImage"` +} + +type WorkerPoolStatus struct { +} + +// WorkerPool is the Schema for the workerpools API +// +genclient +// +kubebuilder:object:generate=true +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced,shortName=workerpool +// +kubebuilder:subresource:status +type WorkerPool struct { + metav1.TypeMeta `json:",inline"` + + // metadata is a standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // spec defines the desired state of WorkerPool + // +required + Spec WorkerPoolSpec `json:"spec"` + + // status is the observed state of WorkerPool + // +optional + Status WorkerPoolStatus `json:"status,omitempty"` +} + +// WorkerPoolList contains a list of WorkerPools. +// +kubebuilder:object:generate=true +// +kubebuilder:object:root=true +type WorkerPoolList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []WorkerPool `json:"items"` +} + +func init() { + SchemeBuilder.Register(&WorkerPool{}, &WorkerPoolList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..a66bb6a6d --- /dev/null +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,344 @@ +//go:build !ignore_autogenerated + +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActorTemplate) DeepCopyInto(out *ActorTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActorTemplate. +func (in *ActorTemplate) DeepCopy() *ActorTemplate { + if in == nil { + return nil + } + out := new(ActorTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActorTemplate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActorTemplateList) DeepCopyInto(out *ActorTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ActorTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActorTemplateList. +func (in *ActorTemplateList) DeepCopy() *ActorTemplateList { + if in == nil { + return nil + } + out := new(ActorTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActorTemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActorTemplateSpec) DeepCopyInto(out *ActorTemplateSpec) { + *out = *in + if in.Containers != nil { + in, out := &in.Containers, &out.Containers + *out = make([]Container, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.SnapshotsConfig = in.SnapshotsConfig + out.WorkerPoolRef = in.WorkerPoolRef + in.Runsc.DeepCopyInto(&out.Runsc) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActorTemplateSpec. +func (in *ActorTemplateSpec) DeepCopy() *ActorTemplateSpec { + if in == nil { + return nil + } + out := new(ActorTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActorTemplateStatus) DeepCopyInto(out *ActorTemplateStatus) { + *out = *in + in.TakeGoldenSnapshotAt.DeepCopyInto(&out.TakeGoldenSnapshotAt) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActorTemplateStatus. +func (in *ActorTemplateStatus) DeepCopy() *ActorTemplateStatus { + if in == nil { + return nil + } + out := new(ActorTemplateStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationConfig) DeepCopyInto(out *AuthenticationConfig) { + *out = *in + if in.GCP != nil { + in, out := &in.GCP, &out.GCP + *out = new(GCPAuthenticationConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationConfig. +func (in *AuthenticationConfig) DeepCopy() *AuthenticationConfig { + if in == nil { + return nil + } + out := new(AuthenticationConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Container) DeepCopyInto(out *Container) { + *out = *in + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]v1.ContainerPort, len(*in)) + copy(*out, *in) + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Container. +func (in *Container) DeepCopy() *Container { + if in == nil { + return nil + } + out := new(Container) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPAuthenticationConfig) DeepCopyInto(out *GCPAuthenticationConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPAuthenticationConfig. +func (in *GCPAuthenticationConfig) DeepCopy() *GCPAuthenticationConfig { + if in == nil { + return nil + } + out := new(GCPAuthenticationConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunscConfig) DeepCopyInto(out *RunscConfig) { + *out = *in + if in.AMD64 != nil { + in, out := &in.AMD64, &out.AMD64 + *out = new(RunscPlatformConfig) + **out = **in + } + if in.ARM64 != nil { + in, out := &in.ARM64, &out.ARM64 + *out = new(RunscPlatformConfig) + **out = **in + } + in.Authentication.DeepCopyInto(&out.Authentication) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunscConfig. +func (in *RunscConfig) DeepCopy() *RunscConfig { + if in == nil { + return nil + } + out := new(RunscConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunscPlatformConfig) DeepCopyInto(out *RunscPlatformConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunscPlatformConfig. +func (in *RunscPlatformConfig) DeepCopy() *RunscPlatformConfig { + if in == nil { + return nil + } + out := new(RunscPlatformConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotsConfig) DeepCopyInto(out *SnapshotsConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotsConfig. +func (in *SnapshotsConfig) DeepCopy() *SnapshotsConfig { + if in == nil { + return nil + } + out := new(SnapshotsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerPool) DeepCopyInto(out *WorkerPool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerPool. +func (in *WorkerPool) DeepCopy() *WorkerPool { + if in == nil { + return nil + } + out := new(WorkerPool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WorkerPool) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerPoolList) DeepCopyInto(out *WorkerPoolList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]WorkerPool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerPoolList. +func (in *WorkerPoolList) DeepCopy() *WorkerPoolList { + if in == nil { + return nil + } + out := new(WorkerPoolList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WorkerPoolList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerPoolSpec) DeepCopyInto(out *WorkerPoolSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerPoolSpec. +func (in *WorkerPoolSpec) DeepCopy() *WorkerPoolSpec { + if in == nil { + return nil + } + out := new(WorkerPoolSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkerPoolStatus) DeepCopyInto(out *WorkerPoolStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkerPoolStatus. +func (in *WorkerPoolStatus) DeepCopy() *WorkerPoolStatus { + if in == nil { + return nil + } + out := new(WorkerPoolStatus) + in.DeepCopyInto(out) + return out +} diff --git a/benchmarking/README.md b/benchmarking/README.md new file mode 100644 index 000000000..5662a3f61 --- /dev/null +++ b/benchmarking/README.md @@ -0,0 +1,86 @@ +# Substrate Benchmarking + +This is the nascent suite for benchmarking Substrate's performance at scale. +It has two components: + +* A metrics scraping stack that leverages Prometheus and Grafana to collect and + visualize metrics (currently only from the locust workers) +* A locust test suite that generates load against Substrate + +## Rebuilding gRPC Python clients + +Make sure you have a virtual environment created (`python3 -m venv venv`) +and activated (`source venv/bin/activate`). + +Install project requirements: `pip install -r requirements.txt` + +Then run `generate_protos.sh` to generate the Python proto clients. + +## Install monitoring + +This must be done first to create the `monitoring` namespace + +```bash +kubectl apply -f monitoring.yaml +``` + +## Deploy Workloads and Demos + +Before running any benchmarks, the corresponding workloads or actor templates must be deployed to the cluster. If you run the benchmarks without deploying their dependent templates first, the Locust tasks will fail to create or locate the required actors. + +> [!IMPORTANT] +> **Caveat:** Workloads/demos must be deployed before the associated benchmarks can be run. Make sure you have sourced the environment configuration file (e.g., `source .ate-dev-env.sh`) in your active terminal to ensure all environment variables (like `BUCKET_NAME` and `PROJECT_ID`) are properly defined. + +### 1. Deploying Scale Workloads (For `ate-api` or `all` benchmarks) +The scale benchmarking tasks (such as `kernelmem`, `sleep`, and `usermem`) require deploying the scale workload templates. + +* **Deploy Workloads:** + ```bash + ./benchmarking/workloads/deploy.sh --deploy + ``` +* **Remove Workloads:** + ```bash + ./benchmarking/workloads/deploy.sh --delete + ``` + +### 2. Deploying the Counter Demo (For `counter` benchmark) +The counter load testing scenario uses the stateful `counter` actor template. + +* **Deploy Counter Demo:** + ```bash + ./hack/install-ate.sh --deploy-demo-counter + ``` +* **Remove Counter Demo:** + ```bash + ./hack/install-ate.sh --delete-demo-counter + ``` + +## Build/Deploy locust + +First, make sure you have sourced `.ate-dev-env.sh` to set up the necessary environment variables: + +* Run `build_and_push.sh` to build and push the image +* Run `deploy_locust.sh` to deploy the locust worker + * You can control what load test is deployed by setting the `LOAD_TYPE` environment variable: + * `LOAD_TYPE=all` (Default) to deploy all tests with the Locust web UI enabled. + * `LOAD_TYPE=ate-api` to deploy the standalone ate-api load test (headless). + * `LOAD_TYPE=counter` to deploy the standalone counter demo load test (headless). + + +## Viewing the results + +### Grafana Dashboards +* Run `kubectl port-forward svc/grafana -n monitoring 3000:3000` +* Visit `http://localhost:3000` in your browser. + +### Locust Web UI (for `LOAD_TYPE=all`) +* Run `kubectl port-forward svc/locust-all -n monitoring 8089:8089` +* Visit `http://localhost:8089` in your browser to configure and start the load test. + +## Future work + +Running discrete load tests and storing the results in a database. + +This will require setting up a Service Account to push results to a +GCS bucket and a controller script to strictly orchestrate the locust +invocation(s), make observations against Prometheus, then push the results. diff --git a/benchmarking/locust/Dockerfile b/benchmarking/locust/Dockerfile new file mode 100644 index 000000000..548fe62b7 --- /dev/null +++ b/benchmarking/locust/Dockerfile @@ -0,0 +1,35 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Stage 1: Dependency builder +FROM python:3.11-slim AS builder +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir --target=/app/deps -r requirements.txt + +# Stage 2: Distroless runner +FROM gcr.io/distroless/python3-debian12 +WORKDIR /app +# Copy the dependencies from builder +COPY --from=builder /app/deps /app/deps +# Copy the locust files +COPY common/ /app/common/ +COPY shapes/ /app/shapes/ +COPY tests/ /app/tests/ + +# Set PYTHONPATH to include /app so modules can find each other +ENV PYTHONPATH=/app:/app/deps +ENV PYTHONUNBUFFERED=1 + + diff --git a/benchmarking/locust/__init__.py b/benchmarking/locust/__init__.py new file mode 100644 index 000000000..b65c2539d --- /dev/null +++ b/benchmarking/locust/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/benchmarking/locust/build_and_push.sh b/benchmarking/locust/build_and_push.sh new file mode 100755 index 000000000..eca307dbe --- /dev/null +++ b/benchmarking/locust/build_and_push.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail +set -u + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +# Source the environment variables if configured +if [[ -f .ate-dev-env.sh ]]; then + source .ate-dev-env.sh +fi + +if [ -z "${PROJECT_ID:-}" ]; then + echo "Error: PROJECT_ID environment variable must be set." >&2 + exit 1 +fi + +IMAGE="us-docker.pkg.dev/${PROJECT_ID}/gcr.io/ate-images/locust-test:latest" + +echo "Building Docker image: $IMAGE" +docker build -t "$IMAGE" -f benchmarking/locust/Dockerfile benchmarking/locust/ + +echo "Pushing Docker image..." +docker push "$IMAGE" + +echo "Done!" diff --git a/benchmarking/locust/common/__init__.py b/benchmarking/locust/common/__init__.py new file mode 100644 index 000000000..b65c2539d --- /dev/null +++ b/benchmarking/locust/common/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/benchmarking/locust/common/ateapi_pb2.py b/benchmarking/locust/common/ateapi_pb2.py new file mode 100644 index 000000000..03cb010b3 --- /dev/null +++ b/benchmarking/locust/common/ateapi_pb2.py @@ -0,0 +1,99 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: ateapi.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'ateapi.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x61teapi.proto\x12\x06\x61teapi\"\x87\x03\n\x05\x41\x63tor\x12\x10\n\x08\x61\x63tor_id\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\x03\x12 \n\x18\x61\x63tor_template_namespace\x18\x03 \x01(\t\x12\x1b\n\x13\x61\x63tor_template_name\x18\x04 \x01(\t\x12$\n\x06status\x18\x05 \x01(\x0e\x32\x14.ateapi.Actor.Status\x12\x1b\n\x13\x61teom_pod_namespace\x18\x06 \x01(\t\x12\x16\n\x0e\x61teom_pod_name\x18\x07 \x01(\t\x12\x14\n\x0c\x61teom_pod_ip\x18\x08 \x01(\t\x12\x15\n\rlast_snapshot\x18\t \x01(\t\x12\x1c\n\x14in_progress_snapshot\x18\n \x01(\t\"v\n\x06Status\x12\x16\n\x12STATUS_UNSPECIFIED\x10\x00\x12\x13\n\x0fSTATUS_RESUMING\x10\x01\x12\x12\n\x0eSTATUS_RUNNING\x10\x02\x12\x15\n\x11STATUS_SUSPENDING\x10\x03\x12\x14\n\x10STATUS_SUSPENDED\x10\x04\"#\n\x0fGetActorRequest\x12\x10\n\x08\x61\x63tor_id\x18\x01 \x01(\t\"0\n\x10GetActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"e\n\x12\x43reateActorRequest\x12\x10\n\x08\x61\x63tor_id\x18\x01 \x01(\t\x12 \n\x18\x61\x63tor_template_namespace\x18\x02 \x01(\t\x12\x1b\n\x13\x61\x63tor_template_name\x18\x03 \x01(\t\"3\n\x13\x43reateActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"\'\n\x13SuspendActorRequest\x12\x10\n\x08\x61\x63tor_id\x18\x01 \x01(\t\"4\n\x14SuspendActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"4\n\x12ResumeActorRequest\x12\x10\n\x08\x61\x63tor_id\x18\x01 \x01(\t\x12\x0c\n\x04\x62oot\x18\x02 \x01(\x08\"3\n\x13ResumeActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"&\n\x12\x44\x65leteActorRequest\x12\x10\n\x08\x61\x63tor_id\x18\x01 \x01(\t\"\x15\n\x13\x44\x65leteActorResponse\"\x14\n\x12ListWorkersRequest\"6\n\x13ListWorkersResponse\x12\x1f\n\x07workers\x18\x01 \x03(\x0b\x32\x0e.ateapi.Worker\"\x13\n\x11ListActorsRequest\"3\n\x12ListActorsResponse\x12\x1d\n\x06\x61\x63tors\x18\x01 \x03(\x0b\x32\r.ateapi.Actor\"\xab\x01\n\x06Worker\x12\x18\n\x10worker_namespace\x18\x01 \x01(\t\x12\x13\n\x0bworker_pool\x18\x02 \x01(\t\x12\x12\n\nworker_pod\x18\x03 \x01(\t\x12\x17\n\x0f\x61\x63tor_namespace\x18\x04 \x01(\t\x12\x16\n\x0e\x61\x63tor_template\x18\x05 \x01(\t\x12\x10\n\x08\x61\x63tor_id\x18\x06 \x01(\t\x12\n\n\x02ip\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\x08 \x01(\x03\"\x13\n\x11\x44\x65\x62ugClearRequest\"\x14\n\x12\x44\x65\x62ugClearResponse\"W\n\x0eMintJWTRequest\x12\x10\n\x08\x61udience\x18\x01 \x03(\t\x12\x0e\n\x06\x61pp_id\x18\x02 \x01(\t\x12\x0f\n\x07user_id\x18\x03 \x01(\t\x12\x12\n\nsession_id\x18\x04 \x01(\t\"&\n\x0fMintJWTResponse\x12\x13\n\x0bsession_jwt\x18\x01 \x01(\t\"k\n\x0fMintCertRequest\x12\x0e\n\x06\x61pp_id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\x12\n\nsession_id\x18\x03 \x01(\t\x12#\n\x1b\x63\x65rtificate_signing_request\x18\x04 \x01(\x0c\"0\n\x10MintCertResponse\x12\x1c\n\x14session_certificates\x18\x01 \x03(\x0c\x32\xcd\x04\n\x07\x43ontrol\x12?\n\x08GetActor\x12\x17.ateapi.GetActorRequest\x1a\x18.ateapi.GetActorResponse\"\x00\x12H\n\x0b\x43reateActor\x12\x1a.ateapi.CreateActorRequest\x1a\x1b.ateapi.CreateActorResponse\"\x00\x12K\n\x0cSuspendActor\x12\x1b.ateapi.SuspendActorRequest\x1a\x1c.ateapi.SuspendActorResponse\"\x00\x12H\n\x0bResumeActor\x12\x1a.ateapi.ResumeActorRequest\x1a\x1b.ateapi.ResumeActorResponse\"\x00\x12H\n\x0b\x44\x65leteActor\x12\x1a.ateapi.DeleteActorRequest\x1a\x1b.ateapi.DeleteActorResponse\"\x00\x12H\n\x0bListWorkers\x12\x1a.ateapi.ListWorkersRequest\x1a\x1b.ateapi.ListWorkersResponse\"\x00\x12\x45\n\nListActors\x12\x19.ateapi.ListActorsRequest\x1a\x1a.ateapi.ListActorsResponse\"\x00\x12\x45\n\nDebugClear\x12\x19.ateapi.DebugClearRequest\x1a\x1a.ateapi.DebugClearResponse\"\x00\x32\x8c\x01\n\x0fSessionIdentity\x12:\n\x07MintJWT\x12\x16.ateapi.MintJWTRequest\x1a\x17.ateapi.MintJWTResponse\x12=\n\x08MintCert\x12\x17.ateapi.MintCertRequest\x1a\x18.ateapi.MintCertResponseB/Z-github.com/agent-substrate/substrate/proto/ateapipbb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ateapi_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'Z-github.com/agent-substrate/substrate/proto/ateapipb' + _globals['_ACTOR']._serialized_start=25 + _globals['_ACTOR']._serialized_end=416 + _globals['_ACTOR_STATUS']._serialized_start=298 + _globals['_ACTOR_STATUS']._serialized_end=416 + _globals['_GETACTORREQUEST']._serialized_start=418 + _globals['_GETACTORREQUEST']._serialized_end=453 + _globals['_GETACTORRESPONSE']._serialized_start=455 + _globals['_GETACTORRESPONSE']._serialized_end=503 + _globals['_CREATEACTORREQUEST']._serialized_start=505 + _globals['_CREATEACTORREQUEST']._serialized_end=606 + _globals['_CREATEACTORRESPONSE']._serialized_start=608 + _globals['_CREATEACTORRESPONSE']._serialized_end=659 + _globals['_SUSPENDACTORREQUEST']._serialized_start=661 + _globals['_SUSPENDACTORREQUEST']._serialized_end=700 + _globals['_SUSPENDACTORRESPONSE']._serialized_start=702 + _globals['_SUSPENDACTORRESPONSE']._serialized_end=754 + _globals['_RESUMEACTORREQUEST']._serialized_start=756 + _globals['_RESUMEACTORREQUEST']._serialized_end=808 + _globals['_RESUMEACTORRESPONSE']._serialized_start=810 + _globals['_RESUMEACTORRESPONSE']._serialized_end=861 + _globals['_DELETEACTORREQUEST']._serialized_start=863 + _globals['_DELETEACTORREQUEST']._serialized_end=901 + _globals['_DELETEACTORRESPONSE']._serialized_start=903 + _globals['_DELETEACTORRESPONSE']._serialized_end=924 + _globals['_LISTWORKERSREQUEST']._serialized_start=926 + _globals['_LISTWORKERSREQUEST']._serialized_end=946 + _globals['_LISTWORKERSRESPONSE']._serialized_start=948 + _globals['_LISTWORKERSRESPONSE']._serialized_end=1002 + _globals['_LISTACTORSREQUEST']._serialized_start=1004 + _globals['_LISTACTORSREQUEST']._serialized_end=1023 + _globals['_LISTACTORSRESPONSE']._serialized_start=1025 + _globals['_LISTACTORSRESPONSE']._serialized_end=1076 + _globals['_WORKER']._serialized_start=1079 + _globals['_WORKER']._serialized_end=1250 + _globals['_DEBUGCLEARREQUEST']._serialized_start=1252 + _globals['_DEBUGCLEARREQUEST']._serialized_end=1271 + _globals['_DEBUGCLEARRESPONSE']._serialized_start=1273 + _globals['_DEBUGCLEARRESPONSE']._serialized_end=1293 + _globals['_MINTJWTREQUEST']._serialized_start=1295 + _globals['_MINTJWTREQUEST']._serialized_end=1382 + _globals['_MINTJWTRESPONSE']._serialized_start=1384 + _globals['_MINTJWTRESPONSE']._serialized_end=1422 + _globals['_MINTCERTREQUEST']._serialized_start=1424 + _globals['_MINTCERTREQUEST']._serialized_end=1531 + _globals['_MINTCERTRESPONSE']._serialized_start=1533 + _globals['_MINTCERTRESPONSE']._serialized_end=1581 + _globals['_CONTROL']._serialized_start=1584 + _globals['_CONTROL']._serialized_end=2173 + _globals['_SESSIONIDENTITY']._serialized_start=2176 + _globals['_SESSIONIDENTITY']._serialized_end=2316 +# @@protoc_insertion_point(module_scope) diff --git a/benchmarking/locust/common/ateapi_pb2_grpc.py b/benchmarking/locust/common/ateapi_pb2_grpc.py new file mode 100644 index 000000000..5ef487418 --- /dev/null +++ b/benchmarking/locust/common/ateapi_pb2_grpc.py @@ -0,0 +1,592 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + +from . import ateapi_pb2 as ateapi__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in ateapi_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) + + +class ControlStub(object): + """Control is the primary RPC interface for Agentic Substrate. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GetActor = channel.unary_unary( + '/ateapi.Control/GetActor', + request_serializer=ateapi__pb2.GetActorRequest.SerializeToString, + response_deserializer=ateapi__pb2.GetActorResponse.FromString, + _registered_method=True) + self.CreateActor = channel.unary_unary( + '/ateapi.Control/CreateActor', + request_serializer=ateapi__pb2.CreateActorRequest.SerializeToString, + response_deserializer=ateapi__pb2.CreateActorResponse.FromString, + _registered_method=True) + self.SuspendActor = channel.unary_unary( + '/ateapi.Control/SuspendActor', + request_serializer=ateapi__pb2.SuspendActorRequest.SerializeToString, + response_deserializer=ateapi__pb2.SuspendActorResponse.FromString, + _registered_method=True) + self.ResumeActor = channel.unary_unary( + '/ateapi.Control/ResumeActor', + request_serializer=ateapi__pb2.ResumeActorRequest.SerializeToString, + response_deserializer=ateapi__pb2.ResumeActorResponse.FromString, + _registered_method=True) + self.DeleteActor = channel.unary_unary( + '/ateapi.Control/DeleteActor', + request_serializer=ateapi__pb2.DeleteActorRequest.SerializeToString, + response_deserializer=ateapi__pb2.DeleteActorResponse.FromString, + _registered_method=True) + self.ListWorkers = channel.unary_unary( + '/ateapi.Control/ListWorkers', + request_serializer=ateapi__pb2.ListWorkersRequest.SerializeToString, + response_deserializer=ateapi__pb2.ListWorkersResponse.FromString, + _registered_method=True) + self.ListActors = channel.unary_unary( + '/ateapi.Control/ListActors', + request_serializer=ateapi__pb2.ListActorsRequest.SerializeToString, + response_deserializer=ateapi__pb2.ListActorsResponse.FromString, + _registered_method=True) + self.DebugClear = channel.unary_unary( + '/ateapi.Control/DebugClear', + request_serializer=ateapi__pb2.DebugClearRequest.SerializeToString, + response_deserializer=ateapi__pb2.DebugClearResponse.FromString, + _registered_method=True) + + +class ControlServicer(object): + """Control is the primary RPC interface for Agentic Substrate. + """ + + def GetActor(self, request, context): + """Get an Actor. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CreateActor(self, request, context): + """Create a new Actor deriving from a given ActorTemplate. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def SuspendActor(self, request, context): + """Suspend a given actor to a new snapshot. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ResumeActor(self, request, context): + """Resume an actor from its latest snapshot. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteActor(self, request, context): + """Delete an actor. Only suspended actors can be deleted. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListWorkers(self, request, context): + """List all workers currently reflected in redis. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListActors(self, request, context): + """List all actors currently reflected in redis. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DebugClear(self, request, context): + """Debugging: drop all data from the ate database. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_ControlServicer_to_server(servicer, server): + rpc_method_handlers = { + 'GetActor': grpc.unary_unary_rpc_method_handler( + servicer.GetActor, + request_deserializer=ateapi__pb2.GetActorRequest.FromString, + response_serializer=ateapi__pb2.GetActorResponse.SerializeToString, + ), + 'CreateActor': grpc.unary_unary_rpc_method_handler( + servicer.CreateActor, + request_deserializer=ateapi__pb2.CreateActorRequest.FromString, + response_serializer=ateapi__pb2.CreateActorResponse.SerializeToString, + ), + 'SuspendActor': grpc.unary_unary_rpc_method_handler( + servicer.SuspendActor, + request_deserializer=ateapi__pb2.SuspendActorRequest.FromString, + response_serializer=ateapi__pb2.SuspendActorResponse.SerializeToString, + ), + 'ResumeActor': grpc.unary_unary_rpc_method_handler( + servicer.ResumeActor, + request_deserializer=ateapi__pb2.ResumeActorRequest.FromString, + response_serializer=ateapi__pb2.ResumeActorResponse.SerializeToString, + ), + 'DeleteActor': grpc.unary_unary_rpc_method_handler( + servicer.DeleteActor, + request_deserializer=ateapi__pb2.DeleteActorRequest.FromString, + response_serializer=ateapi__pb2.DeleteActorResponse.SerializeToString, + ), + 'ListWorkers': grpc.unary_unary_rpc_method_handler( + servicer.ListWorkers, + request_deserializer=ateapi__pb2.ListWorkersRequest.FromString, + response_serializer=ateapi__pb2.ListWorkersResponse.SerializeToString, + ), + 'ListActors': grpc.unary_unary_rpc_method_handler( + servicer.ListActors, + request_deserializer=ateapi__pb2.ListActorsRequest.FromString, + response_serializer=ateapi__pb2.ListActorsResponse.SerializeToString, + ), + 'DebugClear': grpc.unary_unary_rpc_method_handler( + servicer.DebugClear, + request_deserializer=ateapi__pb2.DebugClearRequest.FromString, + response_serializer=ateapi__pb2.DebugClearResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'ateapi.Control', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('ateapi.Control', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class Control(object): + """Control is the primary RPC interface for Agentic Substrate. + """ + + @staticmethod + def GetActor(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/GetActor', + ateapi__pb2.GetActorRequest.SerializeToString, + ateapi__pb2.GetActorResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CreateActor(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/CreateActor', + ateapi__pb2.CreateActorRequest.SerializeToString, + ateapi__pb2.CreateActorResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def SuspendActor(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/SuspendActor', + ateapi__pb2.SuspendActorRequest.SerializeToString, + ateapi__pb2.SuspendActorResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ResumeActor(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/ResumeActor', + ateapi__pb2.ResumeActorRequest.SerializeToString, + ateapi__pb2.ResumeActorResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteActor(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/DeleteActor', + ateapi__pb2.DeleteActorRequest.SerializeToString, + ateapi__pb2.DeleteActorResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListWorkers(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/ListWorkers', + ateapi__pb2.ListWorkersRequest.SerializeToString, + ateapi__pb2.ListWorkersResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListActors(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/ListActors', + ateapi__pb2.ListActorsRequest.SerializeToString, + ateapi__pb2.ListActorsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DebugClear(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.Control/DebugClear', + ateapi__pb2.DebugClearRequest.SerializeToString, + ateapi__pb2.DebugClearResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + +class SessionIdentityStub(object): + """SessionIdentity allows substrate workloads to exchange their + infrastructure-level credentials (k8s service account token, etc.) for a + substrate session-level credential. A given substrate session might migrate + between many different physical workers over the course of its lifecycle, + whereas the session credential's identity will be stable for the life of the + session. + + This service requires authentication. You can authenticate with a Kubernetes + service account token in an `Authorization: Bearer` header, or you can + authenticate with a Kubernetes service account certificate as an mTLS + certificate. (Kubernetes service account certificates do not currently exist + upstream, but we will provide a polyfill based on Pod Certificates). + + The broker will check that the service credentials you authenticated with + belong to a Pod that is currently mapped to the requested session in the + session database. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.MintJWT = channel.unary_unary( + '/ateapi.SessionIdentity/MintJWT', + request_serializer=ateapi__pb2.MintJWTRequest.SerializeToString, + response_deserializer=ateapi__pb2.MintJWTResponse.FromString, + _registered_method=True) + self.MintCert = channel.unary_unary( + '/ateapi.SessionIdentity/MintCert', + request_serializer=ateapi__pb2.MintCertRequest.SerializeToString, + response_deserializer=ateapi__pb2.MintCertResponse.FromString, + _registered_method=True) + + +class SessionIdentityServicer(object): + """SessionIdentity allows substrate workloads to exchange their + infrastructure-level credentials (k8s service account token, etc.) for a + substrate session-level credential. A given substrate session might migrate + between many different physical workers over the course of its lifecycle, + whereas the session credential's identity will be stable for the life of the + session. + + This service requires authentication. You can authenticate with a Kubernetes + service account token in an `Authorization: Bearer` header, or you can + authenticate with a Kubernetes service account certificate as an mTLS + certificate. (Kubernetes service account certificates do not currently exist + upstream, but we will provide a polyfill based on Pod Certificates). + + The broker will check that the service credentials you authenticated with + belong to a Pod that is currently mapped to the requested session in the + session database. + """ + + def MintJWT(self, request, context): + """Request a Session Identity JWT. + + To call this RPC, you must be authenticated as the Kubernetes Pod that is + currently running the requested session. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def MintCert(self, request, context): + """Request a Session Identity Certificate. To call this RPC, you must have + authenticated with a client certificate, not a bearer token. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_SessionIdentityServicer_to_server(servicer, server): + rpc_method_handlers = { + 'MintJWT': grpc.unary_unary_rpc_method_handler( + servicer.MintJWT, + request_deserializer=ateapi__pb2.MintJWTRequest.FromString, + response_serializer=ateapi__pb2.MintJWTResponse.SerializeToString, + ), + 'MintCert': grpc.unary_unary_rpc_method_handler( + servicer.MintCert, + request_deserializer=ateapi__pb2.MintCertRequest.FromString, + response_serializer=ateapi__pb2.MintCertResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'ateapi.SessionIdentity', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('ateapi.SessionIdentity', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class SessionIdentity(object): + """SessionIdentity allows substrate workloads to exchange their + infrastructure-level credentials (k8s service account token, etc.) for a + substrate session-level credential. A given substrate session might migrate + between many different physical workers over the course of its lifecycle, + whereas the session credential's identity will be stable for the life of the + session. + + This service requires authentication. You can authenticate with a Kubernetes + service account token in an `Authorization: Bearer` header, or you can + authenticate with a Kubernetes service account certificate as an mTLS + certificate. (Kubernetes service account certificates do not currently exist + upstream, but we will provide a polyfill based on Pod Certificates). + + The broker will check that the service credentials you authenticated with + belong to a Pod that is currently mapped to the requested session in the + session database. + """ + + @staticmethod + def MintJWT(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.SessionIdentity/MintJWT', + ateapi__pb2.MintJWTRequest.SerializeToString, + ateapi__pb2.MintJWTResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def MintCert(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ateapi.SessionIdentity/MintCert', + ateapi__pb2.MintCertRequest.SerializeToString, + ateapi__pb2.MintCertResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/benchmarking/locust/common/metrics.py b/benchmarking/locust/common/metrics.py new file mode 100644 index 000000000..6f76bf942 --- /dev/null +++ b/benchmarking/locust/common/metrics.py @@ -0,0 +1,95 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from prometheus_client import start_http_server +from opentelemetry import metrics +from opentelemetry.exporter.prometheus import PrometheusMetricReader +from opentelemetry.sdk.metrics import MeterProvider +from locust import events +import logging + +logger = logging.getLogger(__name__) + +_initialized = False +request_counter = None +request_latency = None +locust_users = None + +def init_metrics(): + global _initialized, request_counter, request_latency, locust_users + if _initialized: + logger.info("Metrics already initialized, skipping.") + return + + logger.info("Initializing Prometheus metrics...") + # Start prometheus client metrics server on port 8000 + try: + start_http_server(8000) + except Exception as e: + logger.warning(f"Metrics server already started or failed: {e}") + + _reader = PrometheusMetricReader() + _provider = MeterProvider(metric_readers=[_reader]) + metrics.set_meter_provider(_provider) + + meter = metrics.get_meter("locust_common") + + request_counter = meter.create_counter( + name="locust_requests_total", + description="Total number of requests" + ) + + request_latency = meter.create_histogram( + name="locust_request_duration_milliseconds", + description="Request latency in milliseconds" + ) + + locust_users = meter.create_up_down_counter( + name="locust_users", + description="Number of active locust users" + ) + + _initialized = True + logger.info("Metrics initialized.") + +@events.request.add_listener +def on_request(request_type, name, response_time, response_length, exception, context=None, **kwargs): + if not _initialized: + return + + if context is None: + context = kwargs.get('context', {}) + + user_class = context.get('user_class', 'unknown') + + if 'user_class' in kwargs: + user_class = kwargs['user_class'] + + attributes = { + "method": request_type, + "name": name, + "status": "success" if exception is None else "failure", + "user_class": user_class + } + request_counter.add(1, attributes) + request_latency.record((response_time or 0), attributes) + + +def update_user_count(delta, user_class): + if not _initialized: + logger.warning("Metrics not initialized, cannot update user count.") + return + locust_users.add(delta, {"user_class": user_class}) + + diff --git a/benchmarking/locust/common/trace.py b/benchmarking/locust/common/trace.py new file mode 100644 index 000000000..d06b29f43 --- /dev/null +++ b/benchmarking/locust/common/trace.py @@ -0,0 +1,93 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import events +from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter +from opentelemetry.sdk.trace.sampling import TraceIdRatioBased, Sampler +from opentelemetry.propagate import set_global_textmap +from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator +from opentelemetry.sdk.resources import SERVICE_NAME, Resource +import logging + +logger = logging.getLogger(__name__) + +class UpdatableSampler(Sampler): + def __init__(self, initial_probability=0.0): + self.sampler = TraceIdRatioBased(initial_probability) + self.probability = initial_probability + + def update_probability(self, probability): + self.sampler = TraceIdRatioBased(probability) + self.probability = probability + + def should_sample(self, parent_context, trace_id, name, kind, attributes, links): + return self.sampler.should_sample(parent_context, trace_id, name, kind, attributes, links) + + def get_description(self): + return f"UpdatableSampler(probability={self.probability})" + +_initialized = False +_sampler = UpdatableSampler(0.0) + +def init_tracing(service_name): + global _initialized, _sampler + if _initialized: + logger.info("Tracing already initialized, skipping.") + return + + @events.init_command_line_parser.add_listener + def _(parser): + parser.add_argument( + "--trace-probability", + type=float, + default=0.0, + help="Probability of tracing requests (0.0 to 1.0)" + ) + + @events.init.add_listener + def on_locust_init(environment, **kwargs): + options = environment.parsed_options + probability = getattr(options, 'trace_probability', 0.0) + + _sampler.update_probability(probability) + + resource = Resource(attributes={ + SERVICE_NAME: service_name + }) + provider = TracerProvider(sampler=_sampler, resource=resource) + + # Always add the exporter so it's ready if probability is increased later + processor = BatchSpanProcessor(OTLPSpanExporter()) + provider.add_span_processor(processor) + + trace.set_tracer_provider(provider) + set_global_textmap(TraceContextTextMapPropagator()) + logger.info(f"Tracing initialized for {service_name} with initial probability {probability}") + + @events.test_start.add_listener + def on_test_start(environment, **kwargs): + options = environment.parsed_options + probability = getattr(options, 'trace_probability', 0.0) + _sampler.update_probability(probability) + logger.info(f"Test started, updated trace probability to {probability}") + + _initialized = True + + +def get_tracer(name): + return trace.get_tracer(name) + diff --git a/benchmarking/locust/common/wait_time.py b/benchmarking/locust/common/wait_time.py new file mode 100644 index 000000000..fb7017610 --- /dev/null +++ b/benchmarking/locust/common/wait_time.py @@ -0,0 +1,51 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import events +import random + +_initialized = False + +def init_wait_time(): + """Initialize wait time logic and register command line parser listeners.""" + global _initialized + if _initialized: + return + + @events.init_command_line_parser.add_listener + def on_init_parser(parser): + parser.add_argument( + "--min-wait-time", + type=float, + default=0.0, + env_var="LOCUST_MIN_WAIT_TIME", + help="Minimum global wait time in seconds between tasks for all users", + include_in_web_ui=True + ) + parser.add_argument( + "--max-wait-time", + type=float, + default=0.5, + env_var="LOCUST_MAX_WAIT_TIME", + help="Maximum global wait time in seconds between tasks for all users", + include_in_web_ui=True + ) + + _initialized = True + +def dynamic_wait_time(user_instance): + opts = user_instance.environment.parsed_options + min_wait = opts.min_wait_time if (opts and hasattr(opts, "min_wait_time") and opts.min_wait_time is not None) else 0.0 + max_wait = opts.max_wait_time if (opts and hasattr(opts, "max_wait_time") and opts.max_wait_time is not None) else 0.5 + return random.uniform(min_wait, max_wait) diff --git a/benchmarking/locust/deploy_locust.sh b/benchmarking/locust/deploy_locust.sh new file mode 100755 index 000000000..4e6a9b990 --- /dev/null +++ b/benchmarking/locust/deploy_locust.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail +set -u + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +# Source the environment variables if configured +if [[ -f .ate-dev-env.sh ]]; then + source .ate-dev-env.sh +fi + +if [ -z "${PROJECT_ID:-}" ]; then + echo "Error: PROJECT_ID environment variable must be set." >&2 + exit 1 +fi + +LOAD_TYPE="${LOAD_TYPE:-all}" + +deploy_ate_api() { + echo "Deploying ate-api load test..." + envsubst < benchmarking/locust/manifests/ate-api.yaml | kubectl apply -f - +} + +deploy_counter() { + echo "Deploying counter demo load test..." + envsubst < benchmarking/locust/manifests/counter-demo.yaml | kubectl apply -f - +} + +deploy_all() { + echo "Deploying all load tests with UI..." + envsubst < benchmarking/locust/manifests/all.yaml | kubectl apply -f - +} + +echo "Deploying Locust load with PROJECT_ID=$PROJECT_ID..." + +case "$LOAD_TYPE" in + "ate-api") + deploy_ate_api + ;; + "counter") + deploy_counter + ;; + "all") + deploy_all + ;; + *) + echo "Error: Invalid LOAD_TYPE '$LOAD_TYPE'. Valid options are 'ate-api', 'counter', or 'all'." + exit 1 + ;; +esac + + diff --git a/benchmarking/locust/generate_protos.sh b/benchmarking/locust/generate_protos.sh new file mode 100755 index 000000000..fc8724e9b --- /dev/null +++ b/benchmarking/locust/generate_protos.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail +set -u + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +# Source the environment variables if configured +if [[ -f .ate-dev-env.sh ]]; then + source .ate-dev-env.sh +fi + +PROTO_PATH="proto/ateapipb" +PROTO_FILE="$PROTO_PATH/ateapi.proto" + +# Create and activate virtual environment if it doesn't exist +VENV_DIR="benchmarking/locust/venv" +if [ ! -d "$VENV_DIR" ]; then + echo "Creating virtual environment in $VENV_DIR..." + python3 -m venv "$VENV_DIR" + source "$VENV_DIR/bin/activate" + echo "Installing dependencies..." + pip install --upgrade pip + pip install grpcio-tools +else + echo "Activating virtual environment..." + source "$VENV_DIR/bin/activate" +fi + +echo "Generating Python proto clients from $PROTO_FILE..." + +python3 -m grpc_tools.protoc -I"$PROTO_PATH" --python_out=benchmarking/locust/common/ --grpc_python_out=benchmarking/locust/common/ "$PROTO_FILE" + +# Prepend ASLv2 header to generated files +for file in benchmarking/locust/common/ateapi_pb2.py benchmarking/locust/common/ateapi_pb2_grpc.py; do + if [ -f "$file" ]; then + cat hack/boilerplate/python.txt "$file" > "${file}.tmp" + mv "${file}.tmp" "$file" + fi +done + +# Fix relative import in generated grpc file +GRPC_FILE="benchmarking/locust/common/ateapi_pb2_grpc.py" +if [ -f "$GRPC_FILE" ]; then + sed -i 's/^import ateapi_pb2 as ateapi__pb2/from . import ateapi_pb2 as ateapi__pb2/' "$GRPC_FILE" +fi + +echo "Done!" diff --git a/benchmarking/locust/manifests/all.yaml b/benchmarking/locust/manifests/all.yaml new file mode 100644 index 000000000..ea25038c4 --- /dev/null +++ b/benchmarking/locust/manifests/all.yaml @@ -0,0 +1,91 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: locust-all + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: locust-all + strategy: + type: Recreate + template: + metadata: + labels: + app: locust-all + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + spec: + containers: + - name: locust + image: us-docker.pkg.dev/${PROJECT_ID}/gcr.io/ate-images/locust-test:latest + imagePullPolicy: Always + args: + - "-m" + - "locust" + - "-f" + - "/app/tests" + - "--class-picker" + env: + + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317 + ports: + - name: prometheus + containerPort: 8000 + protocol: TCP + - name: web + containerPort: 8089 + protocol: TCP + volumeMounts: + - name: servicedns-ca + mountPath: /run/servicedns-ca + readOnly: true + resources: + requests: + cpu: "500m" + memory: "512Mi" + volumes: + - name: servicedns-ca + projected: + sources: + - clusterTrustBundle: + signerName: servicedns.podcert.ate.dev/identity + labelSelector: + matchLabels: + podcert.ate.dev/canarying: live + path: ca.crt +--- +apiVersion: v1 +kind: Service +metadata: + name: locust-all + namespace: monitoring +spec: + selector: + app: locust-all + ports: + - name: web + protocol: TCP + port: 8089 + targetPort: 8089 + - name: prometheus + protocol: TCP + port: 8000 + targetPort: 8000 diff --git a/benchmarking/locust/manifests/ate-api.yaml b/benchmarking/locust/manifests/ate-api.yaml new file mode 100644 index 000000000..5f8ae5e84 --- /dev/null +++ b/benchmarking/locust/manifests/ate-api.yaml @@ -0,0 +1,71 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: locust-test + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: locust-test + strategy: + type: Recreate + template: + metadata: + labels: + app: locust-test + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + spec: + containers: + - name: locust + image: us-docker.pkg.dev/${PROJECT_ID}/gcr.io/ate-images/locust-test:latest + imagePullPolicy: Always + args: + - "-m" + - "locust" + - "-f" + - "/app/tests/ate_api.py" + - "--headless" + env: + + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317 + ports: + - name: prometheus + containerPort: 8000 + protocol: TCP + volumeMounts: + - name: servicedns-ca + mountPath: /run/servicedns-ca + readOnly: true + resources: + requests: + cpu: "500m" + memory: "512Mi" + volumes: + - name: servicedns-ca + projected: + sources: + - clusterTrustBundle: + signerName: servicedns.podcert.ate.dev/identity + labelSelector: + matchLabels: + podcert.ate.dev/canarying: live + path: ca.crt + diff --git a/benchmarking/locust/manifests/counter-demo.yaml b/benchmarking/locust/manifests/counter-demo.yaml new file mode 100644 index 000000000..f1f62de96 --- /dev/null +++ b/benchmarking/locust/manifests/counter-demo.yaml @@ -0,0 +1,61 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: locust-counter-demo + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: locust-counter-demo + strategy: + type: Recreate + template: + metadata: + labels: + app: locust-counter-demo + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + spec: + containers: + - name: locust + image: us-docker.pkg.dev/${PROJECT_ID}/gcr.io/ate-images/locust-test:latest + imagePullPolicy: Always + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317 + + args: + - "-m" + - "locust" + - "-f" + - "/app/tests/counter_demo.py" + - "--headless" + - "--users" + - "3" + - "--spawn-rate" + - "3" + + ports: + - name: prometheus + containerPort: 8000 + protocol: TCP + resources: + requests: + cpu: "500m" + memory: "512Mi" diff --git a/benchmarking/locust/manifests/workloads.yaml b/benchmarking/locust/manifests/workloads.yaml new file mode 100644 index 000000000..fc3026ed1 --- /dev/null +++ b/benchmarking/locust/manifests/workloads.yaml @@ -0,0 +1,73 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: locust-workloads + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: locust-workloads + strategy: + type: Recreate + template: + metadata: + labels: + app: locust-workloads + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + spec: + containers: + - name: locust + image: us-docker.pkg.dev/${PROJECT_ID}/gcr.io/ate-images/locust-test:latest + imagePullPolicy: Always + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317 + args: + - "-m" + - "locust" + - "-f" + - "/app/tests/sleep.py" + - "-f" + - "/app/tests/usermem.py" + - "-f" + - "/app/tests/kernelmem.py" + - "--headless" + ports: + - name: prometheus + containerPort: 8000 + protocol: TCP + volumeMounts: + - name: servicedns-ca + mountPath: /run/servicedns-ca + readOnly: true + resources: + requests: + cpu: "500m" + memory: "512Mi" + volumes: + - name: servicedns-ca + projected: + sources: + - clusterTrustBundle: + signerName: servicedns.podcert.ate.dev/identity + labelSelector: + matchLabels: + podcert.ate.dev/canarying: live + path: ca.crt diff --git a/benchmarking/locust/requirements.txt b/benchmarking/locust/requirements.txt new file mode 100644 index 000000000..01298b87f --- /dev/null +++ b/benchmarking/locust/requirements.txt @@ -0,0 +1,25 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +locust==2.32.7 +grpcio +prometheus-client +opentelemetry-api +opentelemetry-sdk +opentelemetry-exporter-prometheus +protobuf +grpcio-tools +opentelemetry-exporter-otlp +opentelemetry-instrumentation-grpc +opentelemetry-instrumentation-requests diff --git a/benchmarking/locust/shapes/__init__.py b/benchmarking/locust/shapes/__init__.py new file mode 100644 index 000000000..b65c2539d --- /dev/null +++ b/benchmarking/locust/shapes/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/benchmarking/locust/shapes/burst_shape.py b/benchmarking/locust/shapes/burst_shape.py new file mode 100644 index 000000000..11eb7e4fa --- /dev/null +++ b/benchmarking/locust/shapes/burst_shape.py @@ -0,0 +1,40 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import LoadTestShape + +class BurstShape(LoadTestShape): + # Overall duration for one burst cycle + cycle_length = 30 + spawn_duration = 10 + + # 3 clients peak per burst, spawned at 1/sec + peak_users = 3 + spawn_rate = 1 + + def tick(self): + run_time = self.get_run_time() + t = run_time % self.cycle_length + + if t < self.spawn_duration: + # Active Spawning Phase + # Target increases steadily towards the peak + target = min(int((t + 1) * self.spawn_rate), self.peak_users) + return (target, self.spawn_rate) + else: + # Idle Phase + # To honor the user's natural expiration, we disable forcefully stopping + # active clients by returning the currently active user count as our target + active_users = self.runner.user_count + return (active_users, self.spawn_rate) diff --git a/benchmarking/locust/tests/__init__.py b/benchmarking/locust/tests/__init__.py new file mode 100644 index 000000000..b65c2539d --- /dev/null +++ b/benchmarking/locust/tests/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/benchmarking/locust/tests/ate_api.py b/benchmarking/locust/tests/ate_api.py new file mode 100644 index 000000000..81dbc1f27 --- /dev/null +++ b/benchmarking/locust/tests/ate_api.py @@ -0,0 +1,189 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import User, task, events +from locust.exception import StopUser +import time +import random +import uuid +import grpc +from common import ateapi_pb2 +from common import ateapi_pb2_grpc +from common.metrics import init_metrics, update_user_count +from common.trace import init_tracing, get_tracer +from common.wait_time import init_wait_time, dynamic_wait_time +from opentelemetry.propagate import inject +import logging + +logger = logging.getLogger(__name__) + +init_tracing("locust-test") + +# Initialize metrics +init_metrics() + +# Initialize wait time +init_wait_time() + +tracer = get_tracer(__name__) + + + +class AteAPIUser(User): + wait_time = dynamic_wait_time + + host = "api.ate-system.svc.cluster.local:443" + + def on_start(self): + update_user_count(1, self.__class__.__name__) + + # Setup gRPC + # Strip protocol prefix if present + target = self.host.replace("http://", "").replace("https://", "") + with open("/run/servicedns-ca/ca.crt", "rb") as f: + ca_cert = f.read() + options = [('grpc.ssl_target_name_override', 'api.ate-system.svc')] + self.channel = grpc.secure_channel(target, grpc.ssl_channel_credentials(root_certificates=ca_cert), options=options) + self.stub = ateapi_pb2_grpc.ControlStub(self.channel) + + # Call CreateActor + self.actor_id = str(uuid.uuid4()) + try: + self.stub.CreateActor( + ateapi_pb2.CreateActorRequest( + actor_id=self.actor_id, + actor_template_namespace="ate-demo-counter", + actor_template_name="counter" + ) + ) + except Exception as e: + print(f"Failed to create actor: {e}") + + def on_stop(self): + update_user_count(-1, self.__class__.__name__) + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to suspend actor: {e}") + self.channel.close() + + @task + def invoke_target(self): + # GetActor + start_time = time.time() + with tracer.start_as_current_span("GetActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + response = self.stub.GetActor( + ateapi_pb2.GetActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="GetActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced GetActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="GetActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced GetActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # ResumeActor + start_time = time.time() + with tracer.start_as_current_span("ResumeActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + response = self.stub.ResumeActor( + ateapi_pb2.ResumeActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # SuspendActor + start_time = time.time() + with tracer.start_as_current_span("SuspendActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + response = self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + diff --git a/benchmarking/locust/tests/counter_demo.py b/benchmarking/locust/tests/counter_demo.py new file mode 100644 index 000000000..2b3baec8f --- /dev/null +++ b/benchmarking/locust/tests/counter_demo.py @@ -0,0 +1,171 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import HttpUser, task, events +import uuid +import time +import logging +import grpc +from common import ateapi_pb2 +from common import ateapi_pb2_grpc + +logger = logging.getLogger(__name__) +from common.metrics import init_metrics, update_user_count + + +from common.trace import init_tracing, get_tracer +from common.wait_time import init_wait_time, dynamic_wait_time +from opentelemetry.propagate import inject + +init_tracing("locust-counter-demo") + +# Initialize metrics +init_metrics() + +# Initialize wait time +init_wait_time() + +tracer = get_tracer(__name__) + + +class CounterUser(HttpUser): + wait_time = dynamic_wait_time + + host = "http://atenet-router.ate-system.svc.cluster.local:80" + api_host = "api.ate-system.svc.cluster.local:443" + + def on_start(self): + update_user_count(1, self.__class__.__name__) + + # Setup gRPC + target = self.api_host.replace("http://", "").replace("https://", "") + with open("/run/servicedns-ca/ca.crt", "rb") as f: + ca_cert = f.read() + options = [('grpc.ssl_target_name_override', 'api.ate-system.svc')] + self.channel = grpc.secure_channel(target, grpc.ssl_channel_credentials(root_certificates=ca_cert), options=options) + self.stub = ateapi_pb2_grpc.ControlStub(self.channel) + + # Call CreateActor + self.actor_id = f"sb-{uuid.uuid4()}" + try: + self.stub.CreateActor( + ateapi_pb2.CreateActorRequest( + actor_id=self.actor_id, + actor_template_namespace="ate-demo-counter", + actor_template_name="counter" + ) + ) + except Exception as e: + logger.error(f"Failed to create actor {self.actor_id}: {e}") + + def on_stop(self): + update_user_count(-1, self.__class__.__name__) + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + logger.error(f"Failed to suspend actor {self.actor_id}: {e}") + self.channel.close() + + @task + def run_and_suspend(self): + # 1. ResumeActor (gRPC) + start_time = time.time() + with tracer.start_as_current_span("ResumeActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + response = self.stub.ResumeActor( + ateapi_pb2.ResumeActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # 2. Run/Increment (HTTP via atenet-router) + start_time = time.time() + with tracer.start_as_current_span("RunCounter") as span: + headers = { + "Host": f"{self.actor_id}.actors.resources.substrate.ate.dev" + } + inject(headers) + try: + response = self.client.post("/", name="RunCounter", headers=headers, context={"user_class": self.__class__.__name__}) + response.raise_for_status() + duration = (time.time() - start_time) * 1000 + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced RunCounter: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + logger.error(f"RunCounter failed: {e}") + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced RunCounter (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # 3. SuspendActor (gRPC) + start_time = time.time() + with tracer.start_as_current_span("SuspendActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + response = self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") diff --git a/benchmarking/locust/tests/kernelmem.py b/benchmarking/locust/tests/kernelmem.py new file mode 100644 index 000000000..f8fce83c6 --- /dev/null +++ b/benchmarking/locust/tests/kernelmem.py @@ -0,0 +1,161 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import User, task, events +import time +import uuid +import grpc +from common import ateapi_pb2 +from common import ateapi_pb2_grpc +from common.metrics import init_metrics, update_user_count +from common.trace import init_tracing, get_tracer +from common.wait_time import init_wait_time, dynamic_wait_time +from opentelemetry.propagate import inject +import logging + +logger = logging.getLogger(__name__) + +init_tracing("locust-workloads") +init_metrics() +init_wait_time() + +tracer = get_tracer(__name__) + + +class KernelMemUser(User): + wait_time = dynamic_wait_time + host = "api.ate-system.svc.cluster.local:443" + template_name = "kernelmem" + + def on_start(self): + update_user_count(1, self.__class__.__name__) + + # Setup gRPC + target = self.host.replace("http://", "").replace("https://", "") + with open("/run/servicedns-ca/ca.crt", "rb") as f: + ca_cert = f.read() + options = [('grpc.ssl_target_name_override', 'api.ate-system.svc')] + self.channel = grpc.secure_channel(target, grpc.ssl_channel_credentials(root_certificates=ca_cert), options=options) + self.stub = ateapi_pb2_grpc.ControlStub(self.channel) + + # Call CreateActor + self.actor_id = f"sb-{uuid.uuid4()}" + try: + self.stub.CreateActor( + ateapi_pb2.CreateActorRequest( + actor_id=self.actor_id, + actor_template_namespace="benchmark-workloads", + actor_template_name=self.template_name + ) + ) + except Exception as e: + print(f"Failed to create actor {self.actor_id}: {e}") + + def on_stop(self): + update_user_count(-1, self.__class__.__name__) + # Suspend first + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to suspend actor {self.actor_id} during teardown: {e}") + + # Delete actor + try: + self.stub.DeleteActor( + ateapi_pb2.DeleteActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to delete actor {self.actor_id}: {e}") + + self.channel.close() + + @task + def workload_cycle(self): + # Start with a half-second sleep + time.sleep(0.5) + + # Suspend + start_time = time.time() + with tracer.start_as_current_span("SuspendActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # Add a sleep between the two operations of half a second + time.sleep(0.5) + + # Revive/Resume + start_time = time.time() + with tracer.start_as_current_span("ResumeActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + self.stub.ResumeActor( + ateapi_pb2.ResumeActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") diff --git a/benchmarking/locust/tests/sleep.py b/benchmarking/locust/tests/sleep.py new file mode 100644 index 000000000..a544bc83d --- /dev/null +++ b/benchmarking/locust/tests/sleep.py @@ -0,0 +1,161 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import User, task, events +import time +import uuid +import grpc +from common import ateapi_pb2 +from common import ateapi_pb2_grpc +from common.metrics import init_metrics, update_user_count +from common.trace import init_tracing, get_tracer +from common.wait_time import init_wait_time, dynamic_wait_time +from opentelemetry.propagate import inject +import logging + +logger = logging.getLogger(__name__) + +init_tracing("locust-workloads") +init_metrics() +init_wait_time() + +tracer = get_tracer(__name__) + + +class SleepUser(User): + wait_time = dynamic_wait_time + host = "api.ate-system.svc.cluster.local:443" + template_name = "sleep" + + def on_start(self): + update_user_count(1, self.__class__.__name__) + + # Setup gRPC + target = self.host.replace("http://", "").replace("https://", "") + with open("/run/servicedns-ca/ca.crt", "rb") as f: + ca_cert = f.read() + options = [('grpc.ssl_target_name_override', 'api.ate-system.svc')] + self.channel = grpc.secure_channel(target, grpc.ssl_channel_credentials(root_certificates=ca_cert), options=options) + self.stub = ateapi_pb2_grpc.ControlStub(self.channel) + + # Call CreateActor + self.actor_id = f"sb-{uuid.uuid4()}" + try: + self.stub.CreateActor( + ateapi_pb2.CreateActorRequest( + actor_id=self.actor_id, + actor_template_namespace="benchmark-workloads", + actor_template_name=self.template_name + ) + ) + except Exception as e: + print(f"Failed to create actor {self.actor_id}: {e}") + + def on_stop(self): + update_user_count(-1, self.__class__.__name__) + # Suspend first + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to suspend actor {self.actor_id} during teardown: {e}") + + # Delete actor + try: + self.stub.DeleteActor( + ateapi_pb2.DeleteActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to delete actor {self.actor_id}: {e}") + + self.channel.close() + + @task + def workload_cycle(self): + # Start with a half-second sleep + time.sleep(0.5) + + # Suspend + start_time = time.time() + with tracer.start_as_current_span("SuspendActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # Add a sleep between the two operations of half a second + time.sleep(0.5) + + # Revive/Resume + start_time = time.time() + with tracer.start_as_current_span("ResumeActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + self.stub.ResumeActor( + ateapi_pb2.ResumeActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") diff --git a/benchmarking/locust/tests/usermem.py b/benchmarking/locust/tests/usermem.py new file mode 100644 index 000000000..0f0adbc6b --- /dev/null +++ b/benchmarking/locust/tests/usermem.py @@ -0,0 +1,161 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from locust import User, task, events +import time +import uuid +import grpc +from common import ateapi_pb2 +from common import ateapi_pb2_grpc +from common.metrics import init_metrics, update_user_count +from common.trace import init_tracing, get_tracer +from common.wait_time import init_wait_time, dynamic_wait_time +from opentelemetry.propagate import inject +import logging + +logger = logging.getLogger(__name__) + +init_tracing("locust-workloads") +init_metrics() +init_wait_time() + +tracer = get_tracer(__name__) + + +class UserMemUser(User): + wait_time = dynamic_wait_time + host = "api.ate-system.svc.cluster.local:443" + template_name = "usermem" + + def on_start(self): + update_user_count(1, self.__class__.__name__) + + # Setup gRPC + target = self.host.replace("http://", "").replace("https://", "") + with open("/run/servicedns-ca/ca.crt", "rb") as f: + ca_cert = f.read() + options = [('grpc.ssl_target_name_override', 'api.ate-system.svc')] + self.channel = grpc.secure_channel(target, grpc.ssl_channel_credentials(root_certificates=ca_cert), options=options) + self.stub = ateapi_pb2_grpc.ControlStub(self.channel) + + # Call CreateActor + self.actor_id = f"sb-{uuid.uuid4()}" + try: + self.stub.CreateActor( + ateapi_pb2.CreateActorRequest( + actor_id=self.actor_id, + actor_template_namespace="benchmark-workloads", + actor_template_name=self.template_name + ) + ) + except Exception as e: + print(f"Failed to create actor {self.actor_id}: {e}") + + def on_stop(self): + update_user_count(-1, self.__class__.__name__) + # Suspend first + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to suspend actor {self.actor_id} during teardown: {e}") + + # Delete actor + try: + self.stub.DeleteActor( + ateapi_pb2.DeleteActorRequest(actor_id=self.actor_id) + ) + except Exception as e: + print(f"Failed to delete actor {self.actor_id}: {e}") + + self.channel.close() + + @task + def workload_cycle(self): + # Start with a half-second sleep + time.sleep(0.5) + + # Suspend + start_time = time.time() + with tracer.start_as_current_span("SuspendActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + self.stub.SuspendActor( + ateapi_pb2.SuspendActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="SuspendActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced SuspendActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + + # Add a sleep between the two operations of half a second + time.sleep(0.5) + + # Revive/Resume + start_time = time.time() + with tracer.start_as_current_span("ResumeActor") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + try: + self.stub.ResumeActor( + ateapi_pb2.ResumeActorRequest(actor_id=self.actor_id), + metadata=metadata + ) + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=None, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor: trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") + except Exception as e: + duration = (time.time() - start_time) * 1000 + events.request.fire( + request_type="grpc", + name="ResumeActor", + response_time=duration, + response_length=0, + exception=e, + user_class=self.__class__.__name__ + ) + if span.get_span_context().trace_flags.sampled: + logger.info(f"Traced ResumeActor (failed): trace_id={span.get_span_context().trace_id:032x}, duration={duration:.2f}ms") diff --git a/benchmarking/monitoring.yaml b/benchmarking/monitoring.yaml new file mode 100644 index 000000000..29072696c --- /dev/null +++ b/benchmarking/monitoring.yaml @@ -0,0 +1,573 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: monitoring +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: prometheus + namespace: monitoring +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: prometheus + namespace: monitoring +rules: +- apiGroups: [""] + resources: ["nodes", "nodes/proxy", "services", "endpoints", "pods"] + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions", "networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: prometheus + namespace: monitoring +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: prometheus +subjects: +- kind: ServiceAccount + name: prometheus + namespace: monitoring +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus-config + namespace: monitoring +data: + prometheus.yml: | + global: + scrape_interval: 10s + scrape_configs: + - job_name: 'kubernetes-pods' + kubernetes_sd_configs: + - role: pod + namespaces: + names: + - monitoring + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: "true" + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus + namespace: monitoring + labels: + app: prometheus +spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + spec: + serviceAccountName: prometheus + containers: + - name: prometheus + image: prom/prometheus:v2.45.0 + args: + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus/" + ports: + - containerPort: 9090 + volumeMounts: + - name: config-volume + mountPath: /etc/prometheus/ + volumes: + - name: config-volume + configMap: + name: prometheus-config +--- +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: monitoring +spec: + selector: + app: prometheus + ports: + - protocol: TCP + port: 9090 + targetPort: 9090 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-datasources + namespace: monitoring +data: + prometheus.yaml: |- + apiVersion: 1 + datasources: + - name: Prometheus + type: prometheus + url: http://prometheus:9090 + access: proxy + isDefault: true +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboards-provider + namespace: monitoring +data: + provider.yaml: |- + apiVersion: 1 + providers: + - name: 'default' + orgId: 1 + folder: 'Locust' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + editable: true + options: + path: /var/lib/grafana/dashboards +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: grafana-dashboards + namespace: monitoring +data: + locust-dashboard.json: |- + { + "uid": "locust-load-test-dashboard", + "title": "ATE API", + "panels": [ + { + "title": "GetActor QPS", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m])) or sum(rate(locust_requests_total{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m]))", "refId": "A", "legendFormat": "Total" }, + { "expr": "sum(rate(locust_requests_total_total{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m])) by (status) or sum(rate(locust_requests_total{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m])) by (status)", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "GetActor Latency 99th Pct", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m])) by (le))", "refId": "A", "legendFormat": "Total" }, + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m])) by (le, status))", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "GetActor Latency Heatmap", + "type": "heatmap", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 8 }, + "targets": [ + { + "expr": "sum(rate(locust_request_duration_milliseconds_bucket{name=\"GetActor\", user_class=\"AteAPIUser\"}[1m])) by (le)", + "refId": "A" + } + ], + + "transformations": [ + { + "id": "labelsToFields", + "options": { + "valueLabel": "le" + } + } + ], + "options": { + "calculate": false, + "yAxis": { + "unit": "ms" + } + } + }, + { + "title": "ResumeActor QPS", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m])) or sum(rate(locust_requests_total{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m]))", "refId": "A", "legendFormat": "Total" }, + { "expr": "sum(rate(locust_requests_total_total{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m])) by (status) or sum(rate(locust_requests_total{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m])) by (status)", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "ResumeActor Latency 99th Pct", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m])) by (le))", "refId": "A", "legendFormat": "Total" }, + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m])) by (le, status))", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "ResumeActor Latency Heatmap", + "type": "heatmap", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 24 }, + "targets": [ + { + "expr": "sum(rate(locust_request_duration_milliseconds_bucket{name=\"ResumeActor\", user_class=\"AteAPIUser\"}[1m])) by (le)", + "refId": "A" + } + ], + + "transformations": [ + { + "id": "labelsToFields", + "options": { + "valueLabel": "le" + } + } + ], + "options": { + "calculate": false, + "yAxis": { + "unit": "ms" + } + } + }, + { + "title": "SuspendActor QPS", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 32 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m])) or sum(rate(locust_requests_total{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m]))", "refId": "A", "legendFormat": "Total" }, + { "expr": "sum(rate(locust_requests_total_total{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m])) by (status) or sum(rate(locust_requests_total{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m])) by (status)", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "SuspendActor Latency 99th Pct", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 32 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m])) by (le))", "refId": "A", "legendFormat": "Total" }, + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m])) by (le, status))", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "SuspendActor Latency Heatmap", + "type": "heatmap", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 40 }, + "targets": [ + { + "expr": "sum(rate(locust_request_duration_milliseconds_bucket{name=\"SuspendActor\", user_class=\"AteAPIUser\"}[1m])) by (le)", + "refId": "A" + } + ], + + "transformations": [ + { + "id": "labelsToFields", + "options": { + "valueLabel": "le" + } + } + ], + "options": { + "calculate": false, + "yAxis": { + "unit": "ms" + } + } + }, + { + "title": "Locust Requesters (Active Users)", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 48 }, + "targets": [ + { "expr": "sum(locust_users{user_class=\"AteAPIUser\"}) by (pod)", "refId": "A" } + ] + } + ], + + "schemaVersion": 38, + "version": 1 + } + locust-counter-dashboard.json: |- + { + "uid": "locust-counter-demo-dashboard", + "title": "Counter Demo", + "panels": [ + { + "title": "ResumeActor QPS", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m])) or sum(rate(locust_requests_total{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m]))", "refId": "A", "legendFormat": "Total" }, + { "expr": "sum(rate(locust_requests_total_total{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m])) by (status) or sum(rate(locust_requests_total{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m])) by (status)", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "ResumeActor Latency 99th Pct", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m])) by (le))", "refId": "A", "legendFormat": "Total" }, + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m])) by (le, status))", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "ResumeActor Latency Heatmap", + "type": "heatmap", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 8 }, + "targets": [ + { + "expr": "sum(rate(locust_request_duration_milliseconds_bucket{name=\"ResumeActor\", user_class=\"CounterUser\"}[1m])) by (le)", + "refId": "A" + } + ], + "transformations": [ + { + "id": "labelsToFields", + "options": { + "valueLabel": "le" + } + } + ], + "options": { + "calculate": false, + "yAxis": { + "unit": "ms" + } + } + }, + { + "title": "RunCounter QPS", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{name=\"RunCounter\", user_class=\"CounterUser\"}[1m])) or sum(rate(locust_requests_total{name=\"RunCounter\", user_class=\"CounterUser\"}[1m]))", "refId": "A", "legendFormat": "Total" }, + { "expr": "sum(rate(locust_requests_total_total{name=\"RunCounter\", user_class=\"CounterUser\"}[1m])) by (status) or sum(rate(locust_requests_total{name=\"RunCounter\", user_class=\"CounterUser\"}[1m])) by (status)", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "RunCounter Latency 99th Pct", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"RunCounter\", user_class=\"CounterUser\"}[1m])) by (le))", "refId": "A", "legendFormat": "Total" }, + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"RunCounter\", user_class=\"CounterUser\"}[1m])) by (le, status))", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "RunCounter Latency Heatmap", + "type": "heatmap", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 24 }, + "targets": [ + { + "expr": "sum(rate(locust_request_duration_milliseconds_bucket{name=\"RunCounter\", user_class=\"CounterUser\"}[1m])) by (le)", + "refId": "A" + } + ], + "transformations": [ + { + "id": "labelsToFields", + "options": { + "valueLabel": "le" + } + } + ], + "options": { + "calculate": false, + "yAxis": { + "unit": "ms" + } + } + }, + { + "title": "SuspendActor QPS", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 32 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m])) or sum(rate(locust_requests_total{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m]))", "refId": "A", "legendFormat": "Total" }, + { "expr": "sum(rate(locust_requests_total_total{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m])) by (status) or sum(rate(locust_requests_total{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m])) by (status)", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "SuspendActor Latency 99th Pct", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 32 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m])) by (le))", "refId": "A", "legendFormat": "Total" }, + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m])) by (le, status))", "refId": "B", "legendFormat": "{{status}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "SuspendActor Latency Heatmap", + "type": "heatmap", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 40 }, + "targets": [ + { + "expr": "sum(rate(locust_request_duration_milliseconds_bucket{name=\"SuspendActor\", user_class=\"CounterUser\"}[1m])) by (le)", + "refId": "A" + } + ], + "transformations": [ + { + "id": "labelsToFields", + "options": { + "valueLabel": "le" + } + } + ], + "options": { + "calculate": false, + "yAxis": { + "unit": "ms" + } + } + }, + { + "title": "Locust Requesters (Active Users)", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 48 }, + "targets": [ + { "expr": "sum(locust_users{user_class=\"CounterUser\"}) by (pod)", "refId": "A" } + ] + } + ], + "schemaVersion": 38, + "version": 1 + } + locust-workloads-dashboard.json: |- + { + "uid": "locust-workloads-dashboard", + "title": "Workloads Benchmarking", + "panels": [ + { + "title": "QPS by Workload", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "targets": [ + { "expr": "sum(rate(locust_requests_total_total{user_class=~\"SleepUser|UserMemUser|KernelMemUser\"}[1m])) by (user_class, name) or sum(rate(locust_requests_total{user_class=~\"SleepUser|UserMemUser|KernelMemUser\"}[1m])) by (user_class, name)", "refId": "A", "legendFormat": "{{user_class}} - {{name}}" } + ], + "fieldConfig": { "defaults": { "unit": "req/sec" } } + }, + { + "title": "Latency 99th Pct by Workload", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "targets": [ + { "expr": "histogram_quantile(0.99, sum(rate(locust_request_duration_milliseconds_bucket{user_class=~\"SleepUser|UserMemUser|KernelMemUser\"}[1m])) by (le, user_class, name))", "refId": "A", "legendFormat": "{{user_class}} - {{name}}" } + ], + "fieldConfig": { "defaults": { "unit": "ms" } } + }, + { + "title": "Active Users by Workload", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 8 }, + "targets": [ + { "expr": "sum(locust_users{user_class=~\"SleepUser|UserMemUser|KernelMemUser\"}) by (user_class)", "refId": "A", "legendFormat": "{{user_class}}" } + ] + } + ], + "schemaVersion": 38, + "version": 1 + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grafana + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: grafana + template: + metadata: + labels: + app: grafana + spec: + containers: + - name: grafana + image: grafana/grafana:10.0.0 + env: + - name: GF_AUTH_ANONYMOUS_ENABLED + value: "true" + - name: GF_AUTH_ANONYMOUS_ORG_ROLE + value: "Admin" + - name: GF_AUTH_DISABLE_LOGIN_FORM + value: "true" + ports: + - containerPort: 3000 + volumeMounts: + - name: grafana-datasources + mountPath: /etc/grafana/provisioning/datasources + - name: grafana-dashboards-provider + mountPath: /etc/grafana/provisioning/dashboards + - name: grafana-dashboards + mountPath: /var/lib/grafana/dashboards + volumes: + - name: grafana-datasources + configMap: + name: grafana-datasources + - name: grafana-dashboards-provider + configMap: + name: grafana-dashboards-provider + - name: grafana-dashboards + configMap: + name: grafana-dashboards +--- +apiVersion: v1 +kind: Service +metadata: + name: grafana + namespace: monitoring +spec: + selector: + app: grafana + ports: + - protocol: TCP + port: 3000 + targetPort: 3000 diff --git a/benchmarking/workloads/deploy.sh b/benchmarking/workloads/deploy.sh new file mode 100755 index 000000000..bcc9f7822 --- /dev/null +++ b/benchmarking/workloads/deploy.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail +set -u + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +# Source the environment variables if configured +if [[ -f .ate-dev-env.sh ]]; then + source .ate-dev-env.sh +fi + +# Ensure BUCKET_NAME is set +if [[ -z "${BUCKET_NAME:-}" ]]; then + echo "Error: BUCKET_NAME environment variable is not set." >&2 + exit 1 +fi + +MANIFEST_TEMPLATE="benchmarking/workloads/manifests/workloads.yaml.tmpl" + +if [[ ! -f "${MANIFEST_TEMPLATE}" ]]; then + echo "Error: ${MANIFEST_TEMPLATE} not found in $(pwd)" >&2 + exit 1 +fi + +usage() { + echo "Usage: $0 [options]" + echo "" + echo "Options:" + echo " --deploy Substitute BUCKET_NAME and deploy workloads to the cluster using ko apply" + echo " --delete Substitute BUCKET_NAME and delete workloads from the cluster using kubectl delete" + echo " -h, --help Show this help message" +} + +deploy() { + echo "Deploying workloads..." + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" "${MANIFEST_TEMPLATE}" \ + | hack/ko.sh apply -f - +} + +delete() { + echo "Deleting workloads..." + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" "${MANIFEST_TEMPLATE}" \ + | kubectl delete --ignore-not-found -f - +} + +if [[ "$#" -eq 0 ]]; then + usage + exit 1 +fi + +action="" +while [[ "$#" -gt 0 ]]; do + case "$1" in + --deploy) + action="deploy" + ;; + --delete) + action="delete" + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Error: Unknown option: $1" >&2 + usage + exit 1 + ;; + esac + shift +done + +if [[ "${action}" == "deploy" ]]; then + deploy +elif [[ "${action}" == "delete" ]]; then + delete +fi diff --git a/benchmarking/workloads/manifests/full_workloads.yaml.tmpl b/benchmarking/workloads/manifests/full_workloads.yaml.tmpl new file mode 100644 index 000000000..dccba1b08 --- /dev/null +++ b/benchmarking/workloads/manifests/full_workloads.yaml.tmpl @@ -0,0 +1,137 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# NOTE this is the YAML template for the full workloads, however performance +# suffers when using it for the following reasons: +# * having multiple worker replicas risks missing caching when resuming a job on a different node, which +# leads to latency due to pulling from GCS +# * The non-sleep workloads currently do not run, since there is not enough disk space to take the golden snapshot. +# +# Once disk space is improved and scheduling optimizations are introduced, we should use this file. + +apiVersion: v1 +kind: Namespace +metadata: + name: benchmark-workloads + +--- + +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: benchmark-ateom + namespace: benchmark-workloads +spec: + replicas: 5 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: sleep + namespace: benchmark-workloads +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: sleep + image: busybox@sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e + command: ["/bin/sleep", "1000000"] + sessionDiscovery: + mapping: + pathPrefix: "/v1/sleep" + protocol: + strategy: CEL + actorIdentity: + cel: "request.host.split('.')[0]" + workerPoolRef: + namespace: benchmark-workloads + name: benchmark-ateom + snapshotsConfig: + location: gs://${BUCKET_NAME}/benchmark-workloads/sleep/ + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: usermem + namespace: benchmark-workloads +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: usermem + image: containerstack/alpine-stress:latest + command: ["stress", "--vm", "1", "--vm-bytes", "1G", "--vm-keep", "--vm-hang", "0"] + sessionDiscovery: + mapping: + pathPrefix: "/v1/usermem" + protocol: + strategy: CEL + actorIdentity: + cel: "request.host.split('.')[0]" + workerPoolRef: + namespace: benchmark-workloads + name: benchmark-ateom + snapshotsConfig: + location: gs://${BUCKET_NAME}/benchmark-workloads/usermem/ + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: kernelmem + namespace: benchmark-workloads +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: kernelmem + image: containerstack/alpine-stress:latest + command: ["sh", "-c", "find /; for i in $(seq 50000); do sleep 10000 & done; sleep 10000"] + sessionDiscovery: + mapping: + pathPrefix: "/v1/kernelmem" + protocol: + strategy: CEL + actorIdentity: + cel: "request.host.split('.')[0]" + workerPoolRef: + namespace: benchmark-workloads + name: benchmark-ateom + snapshotsConfig: + location: gs://${BUCKET_NAME}/benchmark-workloads/kernelmem/ \ No newline at end of file diff --git a/benchmarking/workloads/manifests/workloads.yaml.tmpl b/benchmarking/workloads/manifests/workloads.yaml.tmpl new file mode 100644 index 000000000..1a8d33aba --- /dev/null +++ b/benchmarking/workloads/manifests/workloads.yaml.tmpl @@ -0,0 +1,63 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: benchmark-workloads + +--- + +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: benchmark-ateom + namespace: benchmark-workloads +spec: + replicas: 1 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: sleep + namespace: benchmark-workloads +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: sleep + image: busybox@sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e + command: ["/bin/sleep", "1000000"] + sessionDiscovery: + mapping: + pathPrefix: "/v1/sleep" + protocol: + strategy: CEL + actorIdentity: + cel: "request.host.split('.')[0]" + workerPoolRef: + namespace: benchmark-workloads + name: benchmark-ateom + snapshotsConfig: + location: gs://${BUCKET_NAME}/benchmark-workloads/sleep/ + diff --git a/cmd/kubectl-ate/README.md b/cmd/kubectl-ate/README.md new file mode 100644 index 000000000..5d54d4b2f --- /dev/null +++ b/cmd/kubectl-ate/README.md @@ -0,0 +1,112 @@ +# `kubectl-ate` + +A Kubernetes-native CLI plugin for managing Substrate Actor and Worker lifecycles. + +## Running the CLI + +There are two ways to run the tool, depending on whether you are developing locally or installing it permanently. + +### 1. Install as a native `kubectl` Plugin +You can use `go install` to compile the tool and place the binary directly into your Go bin directory (which should be in your `$PATH`). Because the source folder is named `kubectl-ate`, Kubernetes will automatically recognize the resulting binary! + +```bash +go install ./cmd/kubectl-ate +``` +You can now run it seamlessly anywhere as a native Kubernetes command: `kubectl ate `. + +### 2. Run directly from source (Development) +If you are testing changes to the codebase, you can bypass compilation and run the CLI directly from the source tree: + +```bash +go run ./cmd/kubectl-ate +``` + +## Connection & Auto Port-Forwarding +By default, `kubectl-ate` will automatically read your `~/.kube/config`, discover the `ate-api-server` pods in your cluster, and establish a temporary background port-forward tunnel to execute gRPC calls securely. + +If you prefer to route traffic directly (e.g., through a LoadBalancer or when running natively inside a cluster pod), simply provide the `--endpoint` flag to bypass the tunnel. + +## Tracing +The CLI supports on-demand tracing using the `--trace` flag. When enabled, the CLI will generate a trace ID and signal to the server that it wants the request to be traced. + +**Prerequisites:** + +1. The Google Cloud project must have the **Cloud Trace API** enabled. You can enable it using: +```bash +gcloud services enable cloudtrace.googleapis.com --project=PROJECT_ID +``` + +2. The GKE cluster must have **Managed OpenTelemetry** enabled. If it is not enabled, you can enable it using the following `gcloud` command: + +```bash +gcloud beta container clusters update CLUSTER_NAME \ + --project=PROJECT_ID \ + --managed-otel-scope=COLLECTION_AND_INSTRUMENTATION_COMPONENTS \ + --location=LOCATION +``` + +## Global Flags +These flags can be appended to any command: + +| Flag | Short | Description | Default | +|---|---|---|---| +| `--kubeconfig` | | Path to your kubeconfig file | `~/.kube/config` | +| `--endpoint` | | Manual gRPC endpoint override (e.g., `localhost:8080`) | | +| `--output` | `-o` | Output format (`table`, `json`, `yaml`) | `table` | +| `--trace` | | Enable on-demand tracing for the request | `false` | + +--- + +## Command Reference & Examples + +### Getting Resources +List and inspect the state of actors and workers across the cluster. + +```bash +# List all actors in a clean table format +kubectl ate get actors + +# Get a specific actor by ID and output as raw YAML +kubectl ate get actor -o yaml + +# List all physical workers and see which actors are assigned to them +kubectl ate get workers +``` + +### Actor Lifecycle +Manage the execution state of your workloads. +*(Note: Actors are identified by a user-provided ID, which must be a valid DNS-1123 label)* + +```bash +# Create a new actor deriving from a specific ActorTemplate +kubectl ate create actor my-actor --template=ate-demo-counter/counter-template + +# Resume an actor (assigns it to a free worker and restores its state) +kubectl ate resume actor my-actor + +# Suspend an actor (snapshots its state to storage and frees the worker) +kubectl ate suspend actor my-actor + +# Delete an actor. +kubectl ate delete actor my-actor +``` + +### Administration & Setup +Commands for bootstrapping the Substrate control plane and debugging local environments. + +```bash +# Generate a new CA pool and push it directly to a Kubernetes Secret +kubectl ate admin make-ca-pool \ + --name workerpool-ca-certs \ + --secret-namespace ate-system \ + --ca-id "1" + +# Generate a new JWT authority pool and push it to a Kubernetes Secret +kubectl ate admin make-jwt-pool \ + --name session-id-jwt-pool \ + --secret-namespace ate-system \ + --key-id "1" + +# DANGEROUS: Completely flush all Actor and Worker tracking state from Redis +kubectl ate admin debug-flush-redis +``` diff --git a/cmd/kubectl-ate/cmd/admin.go b/cmd/kubectl-ate/cmd/admin.go new file mode 100644 index 000000000..a98228509 --- /dev/null +++ b/cmd/kubectl-ate/cmd/admin.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var adminCmd = &cobra.Command{ + Use: "admin", + Short: "Administration and debugging commands", +} + +func init() { + rootCmd.AddCommand(adminCmd) +} diff --git a/cmd/kubectl-ate/cmd/admin_debug_redis_flush.go b/cmd/kubectl-ate/cmd/admin_debug_redis_flush.go new file mode 100644 index 000000000..7d82f1d0b --- /dev/null +++ b/cmd/kubectl-ate/cmd/admin_debug_redis_flush.go @@ -0,0 +1,48 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var debugRedisFlushCmd = &cobra.Command{ + Use: "debug-flush-redis", + Short: "DANGEROUS: Flush all data from Redis", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + _, err = apiClient.DebugClear(ctx, &ateapipb.DebugClearRequest{}) + if err != nil { + return fmt.Errorf("failed to flush redis: %w", err) + } + + fmt.Println("Successfully flushed all data from Redis.") + return nil + }, +} + +func init() { + adminCmd.AddCommand(debugRedisFlushCmd) +} diff --git a/cmd/kubectl-ate/cmd/admin_make_ca_pool.go b/cmd/kubectl-ate/cmd/admin_make_ca_pool.go new file mode 100644 index 000000000..448b7341a --- /dev/null +++ b/cmd/kubectl-ate/cmd/admin_make_ca_pool.go @@ -0,0 +1,88 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/internal/localca" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +var caID string +var targetSecretNamespace string +var targetSecretName string + +var makeCaPoolCmd = &cobra.Command{ + Use: "make-ca-pool", + Short: "Make a new secret that contains a CA pool to be used by a signing controller", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + kconfig, err := client.LoadConfig(kubeconfig, k8sContext) + if err != nil { + return fmt.Errorf("while reading kubeconfig: %w", err) + } + + kc, err := kubernetes.NewForConfig(kconfig) + if err != nil { + return fmt.Errorf("while creating Kubernetes client: %w", err) + } + + ca, err := localca.GenerateED25519CA(caID) + if err != nil { + return fmt.Errorf("while generating CA: %w", err) + } + + pool := &localca.Pool{ + CAs: []*localca.CA{ca}, + } + + poolBytes, err := localca.Marshal(pool) + if err != nil { + return fmt.Errorf("while marshaling pool: %w", err) + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: targetSecretNamespace, + Name: targetSecretName, + }, + Data: map[string][]byte{ + "pool": poolBytes, + }, + } + + _, err = kc.CoreV1().Secrets(targetSecretNamespace).Create(ctx, secret, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("while uploading pool state to secret: %w", err) + } + + fmt.Printf("Successfully created CA pool secret %s/%s\n", targetSecretNamespace, targetSecretName) + return nil + }, +} + +func init() { + adminCmd.AddCommand(makeCaPoolCmd) + makeCaPoolCmd.Flags().StringVar(&caID, "ca-id", "", "The ID of the initial CA in the Pool") + makeCaPoolCmd.Flags().StringVar(&targetSecretNamespace, "secret-namespace", "default", "Create the secret in this namespace") + makeCaPoolCmd.Flags().StringVar(&targetSecretName, "name", "", "Create the secret with this name") + makeCaPoolCmd.MarkFlagRequired("name") +} diff --git a/cmd/kubectl-ate/cmd/admin_make_jwt_pool.go b/cmd/kubectl-ate/cmd/admin_make_jwt_pool.go new file mode 100644 index 000000000..539ee72ce --- /dev/null +++ b/cmd/kubectl-ate/cmd/admin_make_jwt_pool.go @@ -0,0 +1,86 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/internal/localjwtauthority" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +var keyID string + +var makeJwtPoolCmd = &cobra.Command{ + Use: "make-jwt-pool", + Short: "Make a new secret that contains a JWT authority pool to be used by the session ID broker", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + kconfig, err := client.LoadConfig(kubeconfig, k8sContext) + if err != nil { + return fmt.Errorf("while reading kubeconfig: %w", err) + } + + kc, err := kubernetes.NewForConfig(kconfig) + if err != nil { + return fmt.Errorf("while creating Kubernetes client: %w", err) + } + + authority, err := localjwtauthority.GenerateECDSAP256Authority(keyID) + if err != nil { + return fmt.Errorf("while generating JWT authority: %w", err) + } + + pool := &localjwtauthority.Pool{ + Authorities: []*localjwtauthority.Authority{authority}, + } + + poolBytes, err := localjwtauthority.Marshal(pool) + if err != nil { + return fmt.Errorf("while marshaling pool: %w", err) + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: targetSecretNamespace, + Name: targetSecretName, + }, + Data: map[string][]byte{ + "pool": poolBytes, + }, + } + + _, err = kc.CoreV1().Secrets(targetSecretNamespace).Create(ctx, secret, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("while uploading pool state to secret: %w", err) + } + + fmt.Printf("Successfully created JWT authority pool secret %s/%s\n", targetSecretNamespace, targetSecretName) + return nil + }, +} + +func init() { + adminCmd.AddCommand(makeJwtPoolCmd) + makeJwtPoolCmd.Flags().StringVar(&keyID, "key-id", "1", "The ID of the initial JWT signing key in the pool") + makeJwtPoolCmd.Flags().StringVar(&targetSecretNamespace, "secret-namespace", "default", "Create the secret in this namespace") + makeJwtPoolCmd.Flags().StringVar(&targetSecretName, "name", "", "Create the secret with this name") + makeJwtPoolCmd.MarkFlagRequired("name") +} diff --git a/cmd/kubectl-ate/cmd/create.go b/cmd/kubectl-ate/cmd/create.go new file mode 100644 index 000000000..c90b80043 --- /dev/null +++ b/cmd/kubectl-ate/cmd/create.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var createCmd = &cobra.Command{ + Use: "create", + Short: "Create a resource", +} + +func init() { + rootCmd.AddCommand(createCmd) +} diff --git a/cmd/kubectl-ate/cmd/create_actor.go b/cmd/kubectl-ate/cmd/create_actor.go new file mode 100644 index 000000000..adbb3d1b1 --- /dev/null +++ b/cmd/kubectl-ate/cmd/create_actor.go @@ -0,0 +1,64 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "strings" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/printer" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var templateFlag string + +var createActorCmd = &cobra.Command{ + Use: "actor [actor-id]", + Short: "Create an actor", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + actorID := args[0] + parts := strings.Split(templateFlag, "/") + if len(parts) != 2 { + return fmt.Errorf("malformed --template: %s (expected /)", templateFlag) + } + + resp, err := apiClient.CreateActor(ctx, &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: parts[0], + ActorTemplateName: parts[1], + ActorId: actorID, + }) + if err != nil { + return fmt.Errorf("failed to create actor: %w", err) + } + + return printer.PrintActor(resp.GetActor(), outputFmt) + }, +} + +func init() { + createActorCmd.Flags().StringVarP(&templateFlag, "template", "t", "", "Template to derive the actor from in / format (required)") + _ = createActorCmd.MarkFlagRequired("template") + createCmd.AddCommand(createActorCmd) +} diff --git a/cmd/kubectl-ate/cmd/delete.go b/cmd/kubectl-ate/cmd/delete.go new file mode 100644 index 000000000..6eadc7ef7 --- /dev/null +++ b/cmd/kubectl-ate/cmd/delete.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var deleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a resource", +} + +func init() { + rootCmd.AddCommand(deleteCmd) +} diff --git a/cmd/kubectl-ate/cmd/delete_actor.go b/cmd/kubectl-ate/cmd/delete_actor.go new file mode 100644 index 000000000..c26eba013 --- /dev/null +++ b/cmd/kubectl-ate/cmd/delete_actor.go @@ -0,0 +1,52 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var deleteActorCmd = &cobra.Command{ + Use: "actor [actor-id]", + Short: "Delete an actor", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + c, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return err + } + defer c.Close() + + id := args[0] + _, err = c.ControlClient.DeleteActor(ctx, &ateapipb.DeleteActorRequest{ + ActorId: id, + }) + if err != nil { + return err + } + + fmt.Printf("actor %q deleted\n", id) + return nil + }, +} + +func init() { + deleteCmd.AddCommand(deleteActorCmd) +} diff --git a/cmd/kubectl-ate/cmd/get.go b/cmd/kubectl-ate/cmd/get.go new file mode 100644 index 000000000..2979884f2 --- /dev/null +++ b/cmd/kubectl-ate/cmd/get.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var getCmd = &cobra.Command{ + Use: "get", + Short: "Display one or many resources", +} + +func init() { + rootCmd.AddCommand(getCmd) +} diff --git a/cmd/kubectl-ate/cmd/get_actors.go b/cmd/kubectl-ate/cmd/get_actors.go new file mode 100644 index 000000000..623f55d2e --- /dev/null +++ b/cmd/kubectl-ate/cmd/get_actors.go @@ -0,0 +1,60 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/printer" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var getActorsCmd = &cobra.Command{ + Use: "actors [actor-id]", + Aliases: []string{"actor"}, + Short: "List all actors or get a specific actor", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + // 1. Connect to API Server + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + // 2. Handle Get Single Actor + if len(args) > 0 { + resp, err := apiClient.GetActor(ctx, &ateapipb.GetActorRequest{ActorId: args[0]}) + if err != nil { + return fmt.Errorf("failed to get actor: %w", err) + } + return printer.PrintActor(resp.GetActor(), outputFmt) + } + + // 3. Handle List All Actors + resp, err := apiClient.ListActors(ctx, &ateapipb.ListActorsRequest{}) + if err != nil { + return fmt.Errorf("failed to list actors: %w", err) + } + return printer.PrintActors(resp.GetActors(), outputFmt) + }, +} + +func init() { + getCmd.AddCommand(getActorsCmd) +} diff --git a/cmd/kubectl-ate/cmd/get_workers.go b/cmd/kubectl-ate/cmd/get_workers.go new file mode 100644 index 000000000..9065cf4b6 --- /dev/null +++ b/cmd/kubectl-ate/cmd/get_workers.go @@ -0,0 +1,48 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/printer" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var getWorkersCmd = &cobra.Command{ + Use: "workers", + Aliases: []string{"worker"}, + Short: "List all workers", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + resp, err := apiClient.ListWorkers(ctx, &ateapipb.ListWorkersRequest{}) + if err != nil { + return fmt.Errorf("failed to list workers: %w", err) + } + return printer.PrintWorkers(resp.GetWorkers(), outputFmt) + }, +} + +func init() { + getCmd.AddCommand(getWorkersCmd) +} diff --git a/cmd/kubectl-ate/cmd/logs.go b/cmd/kubectl-ate/cmd/logs.go new file mode 100644 index 000000000..899d1a9cf --- /dev/null +++ b/cmd/kubectl-ate/cmd/logs.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var logsCmd = &cobra.Command{ + Use: "logs", + Short: "Print the logs for a resource", +} + +func init() { + rootCmd.AddCommand(logsCmd) +} diff --git a/cmd/kubectl-ate/cmd/logs_actors.go b/cmd/kubectl-ate/cmd/logs_actors.go new file mode 100644 index 000000000..6496e8d67 --- /dev/null +++ b/cmd/kubectl-ate/cmd/logs_actors.go @@ -0,0 +1,151 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "bufio" + "encoding/json" + "fmt" + "io" + "os" + "strings" + "time" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" +) + +var rawOutput bool + +var logsActorsCmd = &cobra.Command{ + Use: "actors ", + Aliases: []string{"actor"}, + Short: "Stream logs for a specific actor", + Args: cobra.ExactArgs(1), + RunE: runLogsActor, +} + +func init() { + logsActorsCmd.Flags().BoolVar(&rawOutput, "raw", false, "Output raw JSON log lines instead of pretty-printed format") + logsCmd.AddCommand(logsActorsCmd) +} + +func runLogsActor(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + actorID := args[0] + + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + k8sClient, err := client.NewK8sClientset(kubeconfig, k8sContext) + if err != nil { + return fmt.Errorf("failed to create kubernetes client: %w", err) + } + + actorResp, err := apiClient.GetActor(ctx, &ateapipb.GetActorRequest{ActorId: actorID}) + if err != nil { + return fmt.Errorf("failed to get actor: %w", err) + } + + actor := actorResp.GetActor() + podName := actor.GetAteomPodName() + namespace := actor.GetAteomPodNamespace() + + if podName == "" || namespace == "" || actor.GetStatus() != ateapipb.Actor_STATUS_RUNNING { + return fmt.Errorf("actor %s is not currently running on any worker pod", actorID) + } + + opts := &corev1.PodLogOptions{ + Follow: false, + } + + req := k8sClient.CoreV1().Pods(namespace).GetLogs(podName, opts) + stream, err := req.Stream(ctx) + if err != nil { + return fmt.Errorf("failed to stream logs from pod %s: %w", podName, err) + } + defer stream.Close() + + scanner := bufio.NewScanner(stream) + for scanner.Scan() { + filterAndDisplayLogLine(scanner.Text(), actorID, os.Stdout, rawOutput) + } + if err := scanner.Err(); err != nil { + return fmt.Errorf("error reading log stream: %w", err) + } + + return nil +} + +func filterAndDisplayLogLine(line, targetActorID string, w io.Writer, raw bool) bool { + var m map[string]any + if err := json.Unmarshal([]byte(line), &m); err != nil { + return false + } + labelsAny, ok := m["logging.googleapis.com/labels"] + if !ok { + labelsAny, ok = m["labels"] + if !ok { + return false + } + } + labels, ok := labelsAny.(map[string]any) + if !ok { + return false + } + actorID, ok := labels["ate.dev/actor_id"].(string) + if !ok || actorID != targetActorID { + return false + } + + if raw { + fmt.Fprintln(w, line) + return true + } + + timeStr := "" + if tVal, ok := m["time"].(string); ok { + if t, err := time.Parse(time.RFC3339Nano, tVal); err == nil { + timeStr = t.Format("2006-01-02 15:04:05") + } else if t, err := time.Parse(time.RFC3339, tVal); err == nil { + timeStr = t.Format("2006-01-02 15:04:05") + } else { + timeStr = tVal + } + } + + levelStr := "INFO" + if lVal, ok := m["level"].(string); ok { + levelStr = strings.ToUpper(lVal) + } + + msgStr := "" + if mVal, ok := m["msg"].(string); ok { + msgStr = mVal + } else if mVal, ok := m["message"].(string); ok { + msgStr = mVal + } + + if timeStr != "" { + fmt.Fprintf(w, "[%s] ", timeStr) + } + fmt.Fprintf(w, "[%s] %s\n", levelStr, msgStr) + return true +} diff --git a/cmd/kubectl-ate/cmd/logs_actors_test.go b/cmd/kubectl-ate/cmd/logs_actors_test.go new file mode 100644 index 000000000..db26c27ac --- /dev/null +++ b/cmd/kubectl-ate/cmd/logs_actors_test.go @@ -0,0 +1,105 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "bytes" + "strings" + "testing" +) + +func TestFilterAndDisplayLogLine(t *testing.T) { + tests := []struct { + name string + line string + targetActorID string + raw bool + wantMatched bool + wantOutput string + }{ + { + name: "matching actor, pretty printed with RFC3339Nano", + line: `{"time":"2026-05-16T01:03:38.602878302Z","level":"info","msg":"Count","logging.googleapis.com/labels":{"ate.dev/actor_id":"act-1"}}`, + targetActorID: "act-1", + raw: false, + wantMatched: true, + wantOutput: `[2026-05-16 01:03:38] [INFO] Count`, + }, + { + name: "matching actor, pretty printed with message key", + line: `{"time":"2026-05-16T01:03:38Z","level":"warn","message":"Hello","logging.googleapis.com/labels":{"ate.dev/actor_id":"act-1"}}`, + targetActorID: "act-1", + raw: false, + wantMatched: true, + wantOutput: `[2026-05-16 01:03:38] [WARN] Hello`, + }, + { + name: "matching actor, pretty printed with no timestamp fallback", + line: `{"level":"error","msg":"Failed","logging.googleapis.com/labels":{"ate.dev/actor_id":"act-1"}}`, + targetActorID: "act-1", + raw: false, + wantMatched: true, + wantOutput: `[ERROR] Failed`, + }, + { + name: "matching actor, raw output requested", + line: `{"time":"2026-05-16T01:03:38.602878302Z","level":"info","msg":"Count","logging.googleapis.com/labels":{"ate.dev/actor_id":"act-1"}}`, + targetActorID: "act-1", + raw: true, + wantMatched: true, + wantOutput: `{"time":"2026-05-16T01:03:38.602878302Z","level":"info","msg":"Count","logging.googleapis.com/labels":{"ate.dev/actor_id":"act-1"}}`, + }, + { + name: "matching actor, fallback to standard labels key", + line: `{"time":"2026-05-16T01:03:38.602878302Z","level":"info","msg":"Count","labels":{"ate.dev/actor_id":"act-1"}}`, + targetActorID: "act-1", + raw: false, + wantMatched: true, + wantOutput: `[2026-05-16 01:03:38] [INFO] Count`, + }, + { + name: "non-matching actor", + line: `{"message":"Hello world","logging.googleapis.com/labels":{"ate.dev/actor_id":"act-2"}}`, + targetActorID: "act-1", + raw: false, + wantMatched: false, + wantOutput: "", + }, + { + name: "invalid json line", + line: "not a json line", + targetActorID: "act-1", + raw: false, + wantMatched: false, + wantOutput: "", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + var buf bytes.Buffer + matched := filterAndDisplayLogLine(tc.line, tc.targetActorID, &buf, tc.raw) + + if matched != tc.wantMatched { + t.Errorf("got matched = %v, want %v", matched, tc.wantMatched) + } + + gotOutput := strings.TrimSpace(buf.String()) + if gotOutput != tc.wantOutput { + t.Errorf("got output %q, want %q", gotOutput, tc.wantOutput) + } + }) + } +} diff --git a/cmd/kubectl-ate/cmd/resume.go b/cmd/kubectl-ate/cmd/resume.go new file mode 100644 index 000000000..0a9751f3d --- /dev/null +++ b/cmd/kubectl-ate/cmd/resume.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var resumeCmd = &cobra.Command{ + Use: "resume", + Short: "Resume a resource", +} + +func init() { + rootCmd.AddCommand(resumeCmd) +} diff --git a/cmd/kubectl-ate/cmd/resume_actor.go b/cmd/kubectl-ate/cmd/resume_actor.go new file mode 100644 index 000000000..aa385162f --- /dev/null +++ b/cmd/kubectl-ate/cmd/resume_actor.go @@ -0,0 +1,55 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/printer" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var bootFlag bool + +var resumeActorCmd = &cobra.Command{ + Use: "actor [actor-id]", + Short: "Resume an actor", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + resp, err := apiClient.ResumeActor(ctx, &ateapipb.ResumeActorRequest{ + ActorId: args[0], + Boot: bootFlag, + }) + if err != nil { + return fmt.Errorf("failed to resume actor: %w", err) + } + + return printer.PrintActor(resp.GetActor(), outputFmt) + }, +} + +func init() { + resumeActorCmd.Flags().BoolVarP(&bootFlag, "boot", "", false, "Skip golden snapshot and boot from scratch.") + resumeCmd.AddCommand(resumeActorCmd) +} diff --git a/cmd/kubectl-ate/cmd/root.go b/cmd/kubectl-ate/cmd/root.go new file mode 100644 index 000000000..c69bd0ca3 --- /dev/null +++ b/cmd/kubectl-ate/cmd/root.go @@ -0,0 +1,58 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var ( + kubeconfig string + k8sContext string + endpoint string + outputFmt string + traceEnabled bool +) + +var rootCmd = &cobra.Command{ + Use: "kubectl-ate", + Short: "A kubectl plugin for managing Agent Substrate environments", + Long: `kubectl ate is a CLI tool to manage Actor and Worker lifecycles in an Agent Substrate.`, + SilenceUsage: true, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + if outputFmt != "table" && outputFmt != "json" && outputFmt != "yaml" { + return fmt.Errorf("invalid output format %q. Must be one of: table, json, yaml", outputFmt) + } + return nil + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + os.Exit(1) + } +} + +func init() { + // Persistent flags are available to this command and all subcommands + rootCmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to the kubeconfig file") + rootCmd.PersistentFlags().StringVar(&k8sContext, "context", "", "The name of the kubeconfig context to use") + rootCmd.PersistentFlags().StringVar(&endpoint, "endpoint", "", "Manual override for the gRPC target (e.g., localhost:8080). If omitted, automatically port-forwards.") + rootCmd.PersistentFlags().StringVarP(&outputFmt, "output", "o", "table", "Output format. One of: table|json|yaml") + rootCmd.PersistentFlags().BoolVar(&traceEnabled, "trace", false, "Enable tracing for the request") +} diff --git a/cmd/kubectl-ate/cmd/suspend.go b/cmd/kubectl-ate/cmd/suspend.go new file mode 100644 index 000000000..b2a03ec43 --- /dev/null +++ b/cmd/kubectl-ate/cmd/suspend.go @@ -0,0 +1,28 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var suspendCmd = &cobra.Command{ + Use: "suspend", + Short: "Suspend a resource", +} + +func init() { + rootCmd.AddCommand(suspendCmd) +} diff --git a/cmd/kubectl-ate/cmd/suspend_actor.go b/cmd/kubectl-ate/cmd/suspend_actor.go new file mode 100644 index 000000000..ae7aa9920 --- /dev/null +++ b/cmd/kubectl-ate/cmd/suspend_actor.go @@ -0,0 +1,51 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/printer" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/spf13/cobra" +) + +var suspendActorCmd = &cobra.Command{ + Use: "actor [actor-id]", + Short: "Suspend an actor", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + apiClient, err := client.NewClient(ctx, kubeconfig, k8sContext, endpoint, traceEnabled) + if err != nil { + return fmt.Errorf("failed to connect to ate-api-server: %w", err) + } + defer apiClient.Close() + + resp, err := apiClient.SuspendActor(ctx, &ateapipb.SuspendActorRequest{ + ActorId: args[0], + }) + if err != nil { + return fmt.Errorf("failed to suspend actor: %w", err) + } + + return printer.PrintActor(resp.GetActor(), outputFmt) + }, +} + +func init() { + suspendCmd.AddCommand(suspendActorCmd) +} diff --git a/cmd/kubectl-ate/main.go b/cmd/kubectl-ate/main.go new file mode 100644 index 000000000..1c55eb9ce --- /dev/null +++ b/cmd/kubectl-ate/main.go @@ -0,0 +1,23 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/agent-substrate/substrate/cmd/kubectl-ate/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/cmd/kubectl-ate/pkg/client/builder.go b/cmd/kubectl-ate/pkg/client/builder.go new file mode 100644 index 000000000..d058bcb57 --- /dev/null +++ b/cmd/kubectl-ate/pkg/client/builder.go @@ -0,0 +1,280 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "net/http" + "os" + "sync" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/portforward" + "k8s.io/client-go/transport/spdy" +) + +// Client wraps the gRPC ControlClient and ensures the port-forward connection is closed when done. +type Client struct { + ateapipb.ControlClient + conn *grpc.ClientConn + cancel func() + tracerProvider *sdktrace.TracerProvider +} + +// Close closes the underlying gRPC connection and stops the port-forwarder. +func (c *Client) Close() { + if c.tracerProvider != nil { + // Best practice to ensure clean provider shutdown, even though we skip exporters for clients. + _ = c.tracerProvider.Shutdown(context.Background()) + } + if c.conn != nil { + c.conn.Close() + } + if c.cancel != nil { + c.cancel() + } +} + +// NewClient creates a new Ate API client. If endpoint is empty, it automatically port-forwards +// to the ate-api-server pod in the ate-system namespace. +func NewClient(ctx context.Context, kubeconfigPath, k8sContext, endpoint string, traceEnabled bool) (*Client, error) { + tp, err := initTracing(ctx, traceEnabled) + if err != nil { + return nil, fmt.Errorf("failed to initialize tracing: %w", err) + } + + var cli *Client + if endpoint != "" { + cli, err = dialDirect(kubeconfigPath, k8sContext, endpoint, traceEnabled) + } else { + cli, err = dialPortForward(ctx, kubeconfigPath, k8sContext, traceEnabled) + } + + if err != nil { + _ = tp.Shutdown(ctx) + return nil, err + } + + cli.tracerProvider = tp + return cli, nil +} + +func dialDirect(kubeconfigPath, k8sContext, endpoint string, traceEnabled bool) (*Client, error) { + // Always assume TLS to match production behavior + creds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) + + var opts []grpc.DialOption + opts = append(opts, grpc.WithTransportCredentials(creds)) + opts = append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler())) + + if traceEnabled { + opts = append(opts, grpc.WithUnaryInterceptor(newTraceInterceptor())) + } + + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return nil, fmt.Errorf("failed to dial manual endpoint: %w", err) + } + return &Client{ + ControlClient: ateapipb.NewControlClient(conn), + conn: conn, + cancel: func() {}, + }, nil +} + +// LoadConfig loads a Kubernetes client configuration from the specified kubeconfig path and context. +func LoadConfig(kubeconfigPath, k8sContext string) (*rest.Config, error) { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + loadingRules.ExplicitPath = kubeconfigPath + configOverrides := &clientcmd.ConfigOverrides{CurrentContext: k8sContext} + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides).ClientConfig() +} + +func dialPortForward(ctx context.Context, kubeconfigPath, k8sContext string, traceEnabled bool) (*Client, error) { + config, err := LoadConfig(kubeconfigPath, k8sContext) + if err != nil { + return nil, fmt.Errorf("failed to load kubeconfig: %w", err) + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("failed to create k8s client: %w", err) + } + + // Look up the 'api' Service to dynamically get its pod selector + svc, err := clientset.CoreV1().Services("ate-system").Get(ctx, "api", metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to get api service: %w", err) + } + selector := labels.SelectorFromSet(svc.Spec.Selector).String() + + // Find the pods backing the service + pods, err := clientset.CoreV1().Pods("ate-system").List(ctx, metav1.ListOptions{ + LabelSelector: selector, + }) + if err != nil { + return nil, fmt.Errorf("failed to list ateapi pods: %w", err) + } + if len(pods.Items) == 0 { + return nil, fmt.Errorf("no ate-api-server pods found in ate-system namespace") + } + targetPod := pods.Items[0] + + // Setup port-forwarding + req := clientset.CoreV1().RESTClient().Post(). + Resource("pods"). + Namespace(targetPod.Namespace). + Name(targetPod.Name). + SubResource("portforward") + + transport, upgrader, err := spdy.RoundTripperFor(config) + if err != nil { + return nil, fmt.Errorf("failed to create SPDY transport: %w", err) + } + + dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, http.MethodPost, req.URL()) + + stopCh := make(chan struct{}) + readyCh := make(chan struct{}) + + ports := []string{"0:443"} // Port 0 asks OS for a random available local port + + fw, err := portforward.New(dialer, ports, stopCh, readyCh, io.Discard, io.Discard) + if err != nil { + return nil, fmt.Errorf("failed to create port forwarder: %w", err) + } + + errCh := make(chan error, 1) + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + if err := fw.ForwardPorts(); err != nil { + errCh <- fmt.Errorf("port forwarding failed: %w", err) + } + }() + + // Wait for the tunnel to be ready, an error, or context cancellation + select { + case <-readyCh: + // Tunnel is ready! + case err := <-errCh: + return nil, err + case <-ctx.Done(): + return nil, ctx.Err() + } + + forwardedPorts, err := fw.GetPorts() + if err != nil || len(forwardedPorts) == 0 { + close(stopCh) + return nil, fmt.Errorf("failed to get forwarded ports: %w", err) + } + + localPort := forwardedPorts[0].Local + localEndpoint := fmt.Sprintf("127.0.0.1:%d", localPort) + + // The ate-api-server uses TLS with pod certificates, so we need InsecureSkipVerify + // to talk to it over localhost. + transportCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) + + var opts []grpc.DialOption + opts = append(opts, grpc.WithTransportCredentials(transportCreds)) + opts = append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler())) + + if traceEnabled { + opts = append(opts, grpc.WithUnaryInterceptor(newTraceInterceptor())) + } + + conn, err := grpc.NewClient(localEndpoint, opts...) + if err != nil { + close(stopCh) + return nil, fmt.Errorf("failed to dial gRPC over tunnel: %w", err) + } + + return &Client{ + ControlClient: ateapipb.NewControlClient(conn), + conn: conn, + cancel: func() { + close(stopCh) + wg.Wait() + }, + }, nil +} + +func initTracing(ctx context.Context, enabled bool) (*sdktrace.TracerProvider, error) { + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.UserAgentOriginal("kubectl-ate"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + sampler := sdktrace.NeverSample() + if enabled { + sampler = sdktrace.AlwaysSample() + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithResource(res), + sdktrace.WithSampler(sampler), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.TraceContext{}) + + return tp, nil +} + +func newTraceInterceptor() grpc.UnaryClientInterceptor { + var once sync.Once + return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + tracer := otel.Tracer("kubectl-ate") + ctx, span := tracer.Start(ctx, method) + defer span.End() + + once.Do(func() { + fmt.Fprintf(os.Stderr, "Tracing enabled. Trace ID: %s\n", span.SpanContext().TraceID().String()) + }) + + return invoker(ctx, method, req, reply, cc, opts...) + } +} + +// NewK8sClientset creates a new Kubernetes Clientset using the provided kubeconfig path and context. +func NewK8sClientset(kubeconfigPath, k8sContext string) (*kubernetes.Clientset, error) { + config, err := LoadConfig(kubeconfigPath, k8sContext) + if err != nil { + return nil, err + } + return kubernetes.NewForConfig(config) +} diff --git a/cmd/kubectl-ate/pkg/printer/printer.go b/cmd/kubectl-ate/pkg/printer/printer.go new file mode 100644 index 000000000..65bdbc520 --- /dev/null +++ b/cmd/kubectl-ate/pkg/printer/printer.go @@ -0,0 +1,137 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package printer + +import ( + "encoding/json" + "fmt" + "io" + "os" + "text/tabwriter" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "sigs.k8s.io/yaml" +) + +// PrintActors prints a slice of actors to stdout in the requested format. +func PrintActors(actors []*ateapipb.Actor, format string) error { + return PrintActorsTo(os.Stdout, actors, format) +} + +// PrintActorsTo prints a slice of actors to the provided writer. +func PrintActorsTo(out io.Writer, actors []*ateapipb.Actor, format string) error { + switch format { + case "json", "yaml": + return printProto(out, &ateapipb.ListActorsResponse{Actors: actors}, format) + case "table": + w := tabwriter.NewWriter(out, 0, 0, 3, ' ', 0) + fmt.Fprintln(w, "NAMESPACE\tTEMPLATE\tID\tSTATUS\tATEOM POD\tATEOM IP\tVERSION") + for _, actor := range actors { + ns := actor.GetActorTemplateNamespace() + tmpl := actor.GetActorTemplateName() + id := actor.GetActorId() + status := actor.GetStatus().String() + + worker := "" + if actor.GetAteomPodNamespace() != "" { + worker = actor.GetAteomPodNamespace() + "/" + actor.GetAteomPodName() + } + + version := actor.GetVersion() + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%d\n", ns, tmpl, id, status, worker, actor.GetAteomPodIp(), version) + } + return w.Flush() + default: + return fmt.Errorf("unsupported format %q", format) + } +} + +// PrintWorkers prints a slice of workers to stdout in the requested format. +func PrintWorkers(workers []*ateapipb.Worker, format string) error { + return PrintWorkersTo(os.Stdout, workers, format) +} + +// PrintWorkersTo prints a slice of workers to the provided writer. +func PrintWorkersTo(out io.Writer, workers []*ateapipb.Worker, format string) error { + switch format { + case "json", "yaml": + return printProto(out, &ateapipb.ListWorkersResponse{Workers: workers}, format) + case "table": + w := tabwriter.NewWriter(out, 0, 0, 3, ' ', 0) + fmt.Fprintln(w, "NAMESPACE\tPOOL\tPOD\tSTATUS\tASSIGNED ACTOR") + for _, worker := range workers { + ns := worker.GetWorkerNamespace() + pool := worker.GetWorkerPool() + pod := worker.GetWorkerPod() + + status := "FREE" + assignedActor := "" + if worker.GetActorId() != "" { + status = "ASSIGNED" + assignedActor = fmt.Sprintf("%s/%s/%s", worker.GetActorNamespace(), worker.GetActorTemplate(), worker.GetActorId()) + } + + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", ns, pool, pod, status, assignedActor) + } + return w.Flush() + default: + return fmt.Errorf("unsupported format %q", format) + } +} + +// PrintActor prints a single actor in the requested format. +func PrintActor(actor *ateapipb.Actor, format string) error { + return PrintActors([]*ateapipb.Actor{actor}, format) +} + +func printProto(out io.Writer, msg proto.Message, format string) error { + m := protojson.MarshalOptions{} + b, err := m.Marshal(msg) + if err != nil { + return err + } + + // Normalize JSON output to ensure consistency across environments. + // This works around non-deterministic spacing in protojson. + // See: https://github.com/golang/protobuf/issues/1121 + var obj any + if err := json.Unmarshal(b, &obj); err != nil { + return fmt.Errorf("failed to unmarshal protojson: %w", err) + } + b, err = json.MarshalIndent(obj, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal indent: %w", err) + } + + if format == "yaml" { + yb, err := yaml.JSONToYAML(b) + if err != nil { + return err + } + // The YAML encoder natively appends a trailing newline to the document block. + _, err = out.Write(yb) + return err + } + + // We manually append a trailing newline here so the CLI output doesn't smash + // into the user's terminal prompt. + if _, err = out.Write(b); err != nil { + return err + } + _, err = out.Write([]byte{'\n'}) + return err +} diff --git a/cmd/kubectl-ate/pkg/printer/printer_test.go b/cmd/kubectl-ate/pkg/printer/printer_test.go new file mode 100644 index 000000000..eebe5b097 --- /dev/null +++ b/cmd/kubectl-ate/pkg/printer/printer_test.go @@ -0,0 +1,167 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package printer + +import ( + "bytes" + "testing" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/google/go-cmp/cmp" +) + +func TestPrintActorsTo_Table(t *testing.T) { + var buf bytes.Buffer + actors := []*ateapipb.Actor{ + { + ActorId: "id-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "template-1", + Status: ateapipb.Actor_STATUS_RUNNING, + Version: 2, + AteomPodNamespace: "worker-ns", + AteomPodName: "pod-1", + AteomPodIp: "1.2.3.4", + }, + } + + if err := PrintActorsTo(&buf, actors, "table"); err != nil { + t.Fatalf("unexpected error: %v", err) + } + output := buf.String() + + expected := `NAMESPACE TEMPLATE ID STATUS ATEOM POD ATEOM IP VERSION +default template-1 id-1 STATUS_RUNNING worker-ns/pod-1 1.2.3.4 2 +` + if diff := cmp.Diff(expected, output); diff != "" { + t.Errorf("output mismatch (-want +got):\n%s", diff) + } +} + +func TestPrintActorsTo_JSON(t *testing.T) { + var buf bytes.Buffer + actors := []*ateapipb.Actor{ + { + ActorId: "id-1", + Version: 2, + }, + } + + if err := PrintActorsTo(&buf, actors, "json"); err != nil { + t.Fatalf("unexpected error: %v", err) + } + output := buf.String() + + expected := `{ + "actors": [ + { + "actorId": "id-1", + "version": "2" + } + ] +} +` + if diff := cmp.Diff(expected, output); diff != "" { + t.Errorf("output mismatch (-want +got):\n%s", diff) + } +} + +func TestPrintActorsTo_YAML(t *testing.T) { + var buf bytes.Buffer + actors := []*ateapipb.Actor{ + { + ActorId: "id-1", + Version: 2, + }, + } + + if err := PrintActorsTo(&buf, actors, "yaml"); err != nil { + t.Fatalf("unexpected error: %v", err) + } + output := buf.String() + + expected := `actors: +- actorId: id-1 + version: "2" +` + if diff := cmp.Diff(expected, output); diff != "" { + t.Errorf("output mismatch (-want +got):\n%s", diff) + } +} + +func TestPrintActorsTo_Invalid(t *testing.T) { + var buf bytes.Buffer + err := PrintActorsTo(&buf, nil, "xml") + if err == nil { + t.Errorf("expected error for invalid format, got nil") + } +} + +func TestPrintWorkersTo_Table(t *testing.T) { + var buf bytes.Buffer + workers := []*ateapipb.Worker{ + { + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + ActorNamespace: "default", + ActorTemplate: "template-1", + ActorId: "id-1", + }, + } + + if err := PrintWorkersTo(&buf, workers, "table"); err != nil { + t.Fatalf("unexpected error: %v", err) + } + output := buf.String() + + expected := `NAMESPACE POOL POD STATUS ASSIGNED ACTOR +default pool-1 pod-1 ASSIGNED default/template-1/id-1 +` + if diff := cmp.Diff(expected, output); diff != "" { + t.Errorf("output mismatch (-want +got):\n%s", diff) + } +} + +func TestPrintWorkersTo_Table_Free(t *testing.T) { + var buf bytes.Buffer + workers := []*ateapipb.Worker{ + { + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + }, + } + + if err := PrintWorkersTo(&buf, workers, "table"); err != nil { + t.Fatalf("unexpected error: %v", err) + } + output := buf.String() + + expected := `NAMESPACE POOL POD STATUS ASSIGNED ACTOR +default pool-1 pod-1 FREE +` + if diff := cmp.Diff(expected, output); diff != "" { + t.Errorf("output mismatch (-want +got):\n%s", diff) + } +} + +func TestPrintWorkersTo_Invalid(t *testing.T) { + var buf bytes.Buffer + err := PrintWorkersTo(&buf, nil, "xml") + if err == nil { + t.Errorf("expected error for invalid format, got nil") + } +} diff --git a/cmd/servers/ateapi/ateapi.go b/cmd/servers/ateapi/ateapi.go new file mode 100644 index 000000000..5e42203f9 --- /dev/null +++ b/cmd/servers/ateapi/ateapi.go @@ -0,0 +1,377 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "crypto/tls" + "crypto/x509" + "flag" + "fmt" + "log/slog" + "net" + "net/http" + "os" + "time" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/controlapi" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/sessionidentity" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store/ateredis" + "github.com/agent-substrate/substrate/internal/credbundle" + "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + "github.com/agent-substrate/substrate/pkg/client/informers/externalversions" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/redis/go-redis/v9" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/prometheus" + "go.opentelemetry.io/otel/propagation" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "golang.org/x/oauth2/google" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/reflection" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +var ( + listenAddr = flag.String("grpc-listen-addr", ":443", "Address and port the gRPC server should listen on.") + metricsListenAddr = flag.String("metrics-listen-addr", ":9090", "Address and port the prometheus metrics server should listen on.") + grpcServerCredBundle = flag.String("grpc-server-cred-bundle", "", "File with the server TLS credential bundle.") + + redisClusterAddress = flag.String("redis-cluster-address", "", "The address of the redis cluster.") + redisCACerts = flag.String("redis-ca-certs", "", "The file that contains the CA certificate for Redis cluster.") + redisUseIAMAuth = flag.String("redis-use-iam-auth", "true", "Whether to use Google IAM authentication for Redis/Valkey.") + redisTLSServerName = flag.String("redis-tls-server-name", "", "The ServerName to use for Redis TLS hostname verification.") + redisClientCert = flag.String("redis-client-cert", "", "The file containing client TLS certificate/key credential bundle for Redis/Valkey.") + + clientJWTIssuer = flag.String("client-jwt-issuer", "", "The expected issuer URL for client JWTs.") + clientJWTAudience = flag.String("client-jwt-audience", "", "The expected audience for client JWTs.") + sessionIDJWTPoolFile = flag.String("session-id-jwt-pool", "", "The file that contains the serialized JWT authority pool for signing session JWTs") + + sessionIDCAPoolFile = flag.String("session-id-ca-pool", "", "The file that contains the CA pool for signing session JWTs") + workerpoolCACerts = flag.String("workerpool-ca-certs", "", "The file that contains the CA for verifying workerpool client certificates.") +) + +func main() { + flag.Parse() + ctx := context.Background() + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil))) + + tp, err := initTracing(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to initialize tracing", slog.Any("err", err)) + os.Exit(1) + } + defer func() { + if err := tp.Shutdown(context.Background()); err != nil { + slog.Error("Failed to shutdown TracerProvider", slog.Any("err", err)) + } + }() + + mp, err := initMetrics(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to initialize metrics", slog.Any("err", err)) + os.Exit(1) + } + defer func() { + if err := mp.Shutdown(context.Background()); err != nil { + slog.Error("Failed to shutdown MeterProvider", slog.Any("err", err)) + } + }() + + go func() { + mux := http.NewServeMux() + mux.Handle("/metrics", promhttp.Handler()) + slog.InfoContext(ctx, fmt.Sprintf("Starting Prometheus metrics server on %s", *metricsListenAddr)) + if err := http.ListenAndServe(*metricsListenAddr, mux); err != nil { + slog.Error("Failed to start prometheus metrics server", slog.Any("err", err)) + } + }() + + // For development, certain flags that are likely to be different for each + // developer can optionally be read from environment variables. This is + // helpful because it lets us keep one set of constant Kubernetes manifests + // that source the environment variables from a ConfigMap. Each developer + // can then adapt the deployment to their own GCP project and setup, without + // having to edit the manifests each time they start a new branch. + if *redisClusterAddress == "@env" { + *redisClusterAddress = os.Getenv("ATE_API_REDIS_ADDRESS") + } + if *clientJWTIssuer == "@env" { + *clientJWTIssuer = os.Getenv("ATE_API_K8SJWT_ISSUER") + } + if *redisUseIAMAuth == "@env" { + *redisUseIAMAuth = os.Getenv("ATE_API_REDIS_USE_IAM_AUTH") + } + if *redisTLSServerName == "@env" { + *redisTLSServerName = os.Getenv("ATE_API_REDIS_TLS_SERVER_NAME") + } + if *redisClientCert == "@env" { + *redisClientCert = os.Getenv("ATE_API_REDIS_CLIENT_CERT") + } + + slog.InfoContext(ctx, "Final flag values", + slog.String("grpc-listen-addr", *listenAddr), + slog.String("grpc-server-cred-bundle", *grpcServerCredBundle), + slog.String("redis-cluster-address", *redisClusterAddress), + slog.String("redis-ca-certs", *redisCACerts), + slog.String("redis-use-iam-auth", *redisUseIAMAuth), + slog.String("redis-tls-server-name", *redisTLSServerName), + slog.String("redis-client-cert", *redisClientCert), + slog.String("client-jwt-issuer", *clientJWTIssuer), + slog.String("client-jwt-audience", *clientJWTAudience), + slog.String("session-id-jwt-pool", *sessionIDJWTPoolFile), + slog.String("session-id-ca-pool", *sessionIDCAPoolFile), + slog.String("workerpool-ca-certs", *workerpoolCACerts), + ) + + tlsConfig := &tls.Config{ + MinVersion: tls.VersionTLS12, + } + if *redisCACerts != "" { + ca, err := os.ReadFile(*redisCACerts) + if err != nil { + slog.ErrorContext(ctx, "Failed to read Redis CA cert", slog.Any("err", err)) + os.Exit(1) + } + caPool := x509.NewCertPool() + if !caPool.AppendCertsFromPEM(ca) { + slog.ErrorContext(ctx, "Failed to parse Redis CA cert") + os.Exit(1) + } + slog.InfoContext(ctx, "Using custom CA cert for Redis", slog.String("path", *redisCACerts)) + tlsConfig.RootCAs = caPool + } + + if *redisTLSServerName != "" { + tlsConfig.ServerName = *redisTLSServerName + slog.InfoContext(ctx, "Using custom ServerName for Redis TLS verification", slog.String("name", *redisTLSServerName)) + } + + if *redisClientCert != "" { + cert, err := credbundle.Parse(*redisClientCert) + if err != nil { + slog.ErrorContext(ctx, "Failed to parse Redis client credential bundle", slog.Any("err", err)) + os.Exit(1) + } + tlsConfig.Certificates = []tls.Certificate{*cert} + slog.InfoContext(ctx, "Using client TLS certificate for Redis/Valkey", slog.String("path", *redisClientCert)) + } + + clusterOpts := &redis.ClusterOptions{ + Addrs: []string{*redisClusterAddress}, + TLSConfig: tlsConfig, + } + + if *redisUseIAMAuth != "false" { + creds, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/cloud-platform") + if err != nil { + slog.ErrorContext(ctx, "Failed to find default credentials for Redis IAM auth", slog.Any("err", err)) + os.Exit(1) + } + tokenSource := creds.TokenSource + clusterOpts.CredentialsProvider = func() (string, string) { + tok, err := tokenSource.Token() + if err != nil { + slog.ErrorContext(ctx, "Failed to fetch Redis IAM token", slog.Any("err", err)) + return "default", "" + } + return "default", tok.AccessToken + } + slog.InfoContext(ctx, "Using Google IAM authentication for Redis connection") + } else { + slog.InfoContext(ctx, "Skipping Google IAM authentication for Redis connection") + } + + redisClient := redis.NewClusterClient(clusterOpts) + // Verify connection with retries on startup + var pingErr error + for i := 0; i < 30; i++ { + pingErr = redisClient.Ping(ctx).Err() + if pingErr == nil { + break + } + slog.WarnContext(ctx, "Failed to connect to Redis/Valkey, retrying...", slog.Int("attempt", i+1), slog.Any("err", pingErr)) + select { + case <-ctx.Done(): + pingErr = ctx.Err() + break + case <-time.After(2 * time.Second): + } + } + if pingErr != nil { + slog.ErrorContext(ctx, "Failed to connect to Redis/Valkey after retries", slog.Any("err", pingErr)) + os.Exit(1) + } + + config, err := rest.InClusterConfig() + if err != nil { + slog.ErrorContext(ctx, "Failed to get cluster config", slog.Any("err", err)) + os.Exit(1) + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + slog.ErrorContext(ctx, "Failed to create clientset", slog.Any("err", err)) + os.Exit(1) + } + + ateClient, err := versioned.NewForConfig(config) + if err != nil { + slog.ErrorContext(ctx, "Failed to create ate clientset", slog.Any("err", err)) + os.Exit(1) + } + + var clientCACertPool *x509.CertPool + if *workerpoolCACerts != "" { + // TODO: Periodically reload these to handle rotations. Consult with Tina to see how she did it for client-go. + ca, err := os.ReadFile(*workerpoolCACerts) + if err != nil { + slog.ErrorContext(ctx, "Failed to read workerpool CA", slog.Any("err", err)) + os.Exit(1) + } + clientCACertPool = x509.NewCertPool() + if !clientCACertPool.AppendCertsFromPEM(ca) { + slog.ErrorContext(ctx, "Failed to parse workerpool CA") + os.Exit(1) + } + slog.InfoContext(ctx, "Using custom CA for workerpool clients", slog.String("path", *workerpoolCACerts)) + } + + serverCreds := credentials.NewTLS(&tls.Config{ + GetCertificate: credbundle.Loader(*grpcServerCredBundle), + ClientAuth: tls.VerifyClientCertIfGiven, + ClientCAs: clientCACertPool, + }) + redisPersistence := ateredis.NewPersistence(redisClient) + + ateFactory := externalversions.NewSharedInformerFactory(ateClient, 0) + actorTemplateLister := ateFactory.Api().V1alpha1().ActorTemplates().Lister() + + workerPodInformerFactory, workerPodInformer := controlapi.WorkerPodInformer(clientset) + ateletPodInformerFactory, ateletPodInformer := controlapi.AteletInformer(clientset) + + syncer := controlapi.NewWorkerPoolSyncer(redisPersistence, workerPodInformer) + syncer.Start(ctx) + + stopCh := make(chan struct{}) + defer close(stopCh) + workerPodInformerFactory.Start(stopCh) + ateletPodInformerFactory.Start(stopCh) + ateFactory.Start(stopCh) + + workerPodInformerFactory.WaitForCacheSync(stopCh) + ateletPodInformerFactory.WaitForCacheSync(stopCh) + ateFactory.WaitForCacheSync(stopCh) + + dialer := controlapi.NewAteletDialer(workerPodInformer.GetIndexer(), ateletPodInformer.GetIndexer()) + sm := controlapi.NewService(redisPersistence, actorTemplateLister, dialer) + + sessionIdentitySrv := sessionidentity.New(*clientJWTIssuer, *clientJWTAudience, *sessionIDJWTPoolFile, *sessionIDCAPoolFile, *workerpoolCACerts) + + lisCfg := &net.ListenConfig{} + lis, err := lisCfg.Listen(ctx, "tcp", *listenAddr) + if err != nil { + slog.ErrorContext(ctx, "Failed to start listener", slog.Any("err", err)) + os.Exit(1) + } + + mux := grpc.NewServer( + grpc.Creds(serverCreds), + grpc.StatsHandler(otelgrpc.NewServerHandler()), + grpc.UnaryInterceptor(controlapi.StatusErrorInterceptor), + ) + reflection.Register(mux) + ateapipb.RegisterControlServer(mux, sm) + ateapipb.RegisterSessionIdentityServer(mux, sessionIdentitySrv) + + if err := mux.Serve(lis); err != nil { + slog.ErrorContext(ctx, "Failed to serve", slog.Any("err", err)) + os.Exit(1) + } +} + +func initTracing(ctx context.Context) (*sdktrace.TracerProvider, error) { + exporter, err := otlptracegrpc.New(ctx, + // GKE managed traces doesn't support validating the TLS certs of the collector + otlptracegrpc.WithInsecure(), + ) + if err != nil { + return nil, fmt.Errorf("failed to create OTLP exporter: %w", err) + } + + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.ServiceName("ateapi"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(res), + // Only trace on-demand when signaled by the client (e.g. via --trace flag) + sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.AlwaysSample())), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.TraceContext{}) + + return tp, nil +} + +func initMetrics(ctx context.Context) (*sdkmetric.MeterProvider, error) { + // Prometheus Exporter + promExporter, err := prometheus.New() + if err != nil { + return nil, fmt.Errorf("failed to create Prometheus metric exporter: %w", err) + } + + // OTLP Exporter + otlpExporter, err := otlpmetricgrpc.New(ctx, + otlpmetricgrpc.WithInsecure(), + ) + if err != nil { + return nil, fmt.Errorf("failed to create OTLP metric exporter: %w", err) + } + + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.ServiceName("ateapi"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + mp := sdkmetric.NewMeterProvider( + // Register both readers + sdkmetric.WithReader(promExporter), + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(otlpExporter)), + sdkmetric.WithResource(res), + ) + otel.SetMeterProvider(mp) + + return mp, nil +} diff --git a/cmd/servers/ateapi/controlapi/create_actor.go b/cmd/servers/ateapi/controlapi/create_actor.go new file mode 100644 index 000000000..19628439f --- /dev/null +++ b/cmd/servers/ateapi/controlapi/create_actor.go @@ -0,0 +1,82 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "fmt" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/internal/resources" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + k8serrors "k8s.io/apimachinery/pkg/api/errors" +) + +func (s *Service) CreateActor(ctx context.Context, req *ateapipb.CreateActorRequest) (*ateapipb.CreateActorResponse, error) { + if err := validateCreateActorRequest(req); err != nil { + return nil, err + } + _, err := s.actorTemplateLister.ActorTemplates(req.GetActorTemplateNamespace()).Get(req.GetActorTemplateName()) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil, status.Errorf(codes.FailedPrecondition, "ActorTemplate %s/%s not found", req.GetActorTemplateNamespace(), req.GetActorTemplateName()) + } + return nil, fmt.Errorf("while getting ActorTemplate: %w", err) + } + + id := req.GetActorId() + actor := &ateapipb.Actor{ + ActorId: id, + Version: 1, + Status: ateapipb.Actor_STATUS_SUSPENDED, + ActorTemplateNamespace: req.GetActorTemplateNamespace(), + ActorTemplateName: req.GetActorTemplateName(), + } + err = s.persistence.CreateActor(ctx, actor) + if err != nil { + if errors.Is(err, store.ErrAlreadyExists) { + return nil, status.Errorf(codes.AlreadyExists, "Actor %s already exists", id) + } + return nil, fmt.Errorf("while recording actor: %w", err) + } + + storedActor, err := s.persistence.GetActor(ctx, id) + if err != nil { + return nil, fmt.Errorf("while fetching recorded actor from DB: %w", err) + } + + return &ateapipb.CreateActorResponse{ + Actor: storedActor, + }, nil +} + +func validateCreateActorRequest(req *ateapipb.CreateActorRequest) error { + if req.GetActorTemplateNamespace() == "" { + return status.Error(codes.InvalidArgument, "actor_template_namespace is required") + } + if req.GetActorTemplateName() == "" { + return status.Error(codes.InvalidArgument, "actor_template_name is required") + } + if req.GetActorId() == "" { + return status.Error(codes.InvalidArgument, "actor_id is required") + } + if err := resources.ValidateActorID(req.GetActorId()); err != nil { + return status.Error(codes.InvalidArgument, err.Error()) + } + return nil +} diff --git a/cmd/servers/ateapi/controlapi/debug_clear.go b/cmd/servers/ateapi/controlapi/debug_clear.go new file mode 100644 index 000000000..803b4c673 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/debug_clear.go @@ -0,0 +1,36 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "fmt" + + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +func (s *Service) DebugClear(ctx context.Context, req *ateapipb.DebugClearRequest) (*ateapipb.DebugClearResponse, error) { + if err := validateDebugClearRequest(req); err != nil { + return nil, err + } + if err := s.persistence.DebugClearAll(ctx); err != nil { + return nil, fmt.Errorf("while running DebugClearAll: %w", err) + } + return &ateapipb.DebugClearResponse{}, nil +} + +func validateDebugClearRequest(req *ateapipb.DebugClearRequest) error { + return nil +} diff --git a/cmd/servers/ateapi/controlapi/delete_actor.go b/cmd/servers/ateapi/controlapi/delete_actor.go new file mode 100644 index 000000000..ec4400fb3 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/delete_actor.go @@ -0,0 +1,62 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "fmt" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/internal/resources" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) DeleteActor(ctx context.Context, req *ateapipb.DeleteActorRequest) (*ateapipb.DeleteActorResponse, error) { + if err := validateDeleteActorRequest(req); err != nil { + return nil, err + } + + if err := s.persistence.DeleteActor(ctx, req.GetActorId()); err != nil { + if errors.Is(err, store.ErrNotFound) { + return nil, status.Errorf(codes.NotFound, "Actor %s not found", req.GetActorId()) + } + if errors.Is(err, store.ErrFailedPrecondition) { + actor, getErr := s.persistence.GetActor(ctx, req.GetActorId()) + if getErr == nil { + return nil, status.Errorf(codes.FailedPrecondition, "Actor %s is not suspended (status: %v)", req.GetActorId(), actor.GetStatus()) + } + return nil, status.Errorf(codes.FailedPrecondition, "Actor %s is not suspended", req.GetActorId()) + } + if errors.Is(err, store.ErrPersistenceRetry) { + return nil, status.Error(codes.Aborted, "concurrent update conflict, please retry") + } + return nil, fmt.Errorf("while deleting actor from DB: %w", err) + } + + return &ateapipb.DeleteActorResponse{}, nil +} + +func validateDeleteActorRequest(req *ateapipb.DeleteActorRequest) error { + if req.GetActorId() == "" { + return status.Error(codes.InvalidArgument, "actor_id is required") + } + if err := resources.ValidateActorID(req.GetActorId()); err != nil { + return status.Error(codes.InvalidArgument, err.Error()) + } + return nil +} diff --git a/cmd/servers/ateapi/controlapi/dialer.go b/cmd/servers/ateapi/controlapi/dialer.go new file mode 100644 index 000000000..c8cb66115 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/dialer.go @@ -0,0 +1,99 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "errors" + "fmt" + + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/utils/lru" +) + +var ErrWorkerPodNotFound = errors.New("worker pod not found") + +// AteletDialer handles gRPC connections to Atelet pods. +type AteletDialer struct { + workerIndexer cache.Indexer + ateletIndexer cache.Indexer + ateletConns *lru.Cache +} + +// NewAteletDialer creates a new AteletDialer. +func NewAteletDialer(workerIndexer cache.Indexer, ateletIndexer cache.Indexer) *AteletDialer { + return &AteletDialer{ + workerIndexer: workerIndexer, + ateletIndexer: ateletIndexer, + ateletConns: lru.New(1024), + } +} + +// DialForWorker returns a gRPC connection to the Atelet running on the same node as the specified worker pod. +// Returns ErrWorkerPodNotFound if the worker pod is not found in the informer cache. +func (d *AteletDialer) DialForWorker(workerPodNamespace, workerPodName string) (*grpc.ClientConn, error) { + workerPodKey := workerPodNamespace + "/" + workerPodName + matchingPods, err := d.workerIndexer.ByIndex(byNamespaceAndName, workerPodKey) + if err != nil { + return nil, fmt.Errorf("while finding pod %q: %w", workerPodKey, err) + } + + if len(matchingPods) == 0 { + return nil, ErrWorkerPodNotFound + } + + if len(matchingPods) > 1 { + return nil, fmt.Errorf("expected 1 pod match, got %d", len(matchingPods)) + } + + selectedWorker := matchingPods[0].(*corev1.Pod) + + matchingAtelets, err := d.ateletIndexer.ByIndex(byNode, selectedWorker.Spec.NodeName) + if err != nil { + return nil, fmt.Errorf("while finding atelet for worker pod %q on node %q: %w", workerPodKey, selectedWorker.Spec.NodeName, err) + } + + if len(matchingAtelets) != 1 { + return nil, fmt.Errorf("found %d atelet pods on node %q, expected 1", len(matchingAtelets), selectedWorker.Spec.NodeName) + } + + selectedAtelet := matchingAtelets[0].(*corev1.Pod) + ateletKey := selectedAtelet.ObjectMeta.Namespace + "/" + selectedAtelet.ObjectMeta.Name + + ateletConnAny, ok := d.ateletConns.Get(ateletKey) + if ok { + return ateletConnAny.(*grpc.ClientConn), nil + } + + if len(selectedAtelet.Status.PodIPs) == 0 { + return nil, fmt.Errorf("selected atelet %q has no assigned IPs: %w", selectedAtelet.ObjectMeta.Namespace+"/"+selectedAtelet.ObjectMeta.Name, err) + } + + ateletConn, err := grpc.NewClient( + selectedAtelet.Status.PodIPs[0].IP+":8085", + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithStatsHandler(otelgrpc.NewClientHandler()), + ) + if err != nil { + return nil, fmt.Errorf("while creating atelet gRPC client connection: %w", err) + } + + d.ateletConns.Add(ateletKey, ateletConn) + + return ateletConn, nil +} diff --git a/cmd/servers/ateapi/controlapi/functional_test.go b/cmd/servers/ateapi/controlapi/functional_test.go new file mode 100644 index 000000000..1b43f542e --- /dev/null +++ b/cmd/servers/ateapi/controlapi/functional_test.go @@ -0,0 +1,1318 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "fmt" + "net" + "os" + "os/exec" + "sort" + "strings" + "sync" + "testing" + "time" + + atev1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store/ateredis" + "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + "github.com/agent-substrate/substrate/pkg/client/informers/externalversions" + listersv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/agent-substrate/substrate/proto/ateletpb" + "github.com/alicebob/miniredis/v2" + "github.com/google/go-cmp/cmp" + "github.com/redis/go-redis/v9" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/testing/protocmp" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/envtest" +) + +var ( + testEnv *envtest.Environment + cfg *rest.Config + fakeAtelet = &FakeAteletServer{} +) + +func TestMain(m *testing.M) { + cmd := exec.Command("bash", "../../../../hack/run-tool.sh", "setup-envtest", "use", "--print", "path") + out, err := cmd.Output() + if err != nil { + os.Exit(1) + } + binaryAssetsDirectory := strings.TrimSpace(string(out)) + + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{"../../../../manifests/ate-install/generated"}, + BinaryAssetsDirectory: binaryAssetsDirectory, + } + + cfg, err = testEnv.Start() + if err != nil { + os.Exit(1) + } + + // Create ate-system namespace + k8sClient, err := kubernetes.NewForConfig(cfg) + if err != nil { + os.Exit(1) + } + _, err = k8sClient.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "ate-system"}, + }, metav1.CreateOptions{}) + if err != nil && !strings.Contains(err.Error(), "already exists") { + os.Exit(1) + } + + // Create shared Atelet Pod + ateletPod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "atelet-shared", + Namespace: "ate-system", + Labels: map[string]string{ + "app": "atelet", + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node1", + Containers: []corev1.Container{ + {Name: "main", Image: "nginx"}, + }, + }, + } + createdAtelet, err := k8sClient.CoreV1().Pods("ate-system").Create(context.Background(), ateletPod, metav1.CreateOptions{}) + if err != nil && !strings.Contains(err.Error(), "already exists") { + os.Exit(1) + } + if err == nil { + createdAtelet.Status.PodIPs = []corev1.PodIP{{IP: "127.0.0.1"}} + createdAtelet.Status.Phase = corev1.PodRunning + _, err = k8sClient.CoreV1().Pods("ate-system").UpdateStatus(context.Background(), createdAtelet, metav1.UpdateOptions{}) + if err != nil { + os.Exit(1) + } + } + + // Start Fake Atelet Server on port 8085 + ateletGrpcServer := grpc.NewServer() + ateletpb.RegisterAteomHerderServer(ateletGrpcServer, fakeAtelet) + ateletLis, err := net.Listen("tcp", "127.0.0.1:8085") + if err != nil { + os.Exit(1) + } + go func() { + if err := ateletGrpcServer.Serve(ateletLis); err != nil { + fmt.Printf("atelet grpc server exited: %v\n", err) + } + }() + + code := m.Run() + + ateletGrpcServer.Stop() + + err = testEnv.Stop() + if err != nil { + os.Exit(1) + } + + os.Exit(code) +} + +// FakeAteletServer implements ateletpb.WorkersServer +type FakeAteletServer struct { + ateletpb.UnimplementedAteomHerderServer + + Lock sync.Mutex + + RunCalled bool + + CheckpointCalled bool + + RestoreCalled bool + FailRestore error + RestoreDelay time.Duration +} + +func (f *FakeAteletServer) Reset() { + f.Lock.Lock() + defer f.Lock.Unlock() + + f.RunCalled = false + + f.CheckpointCalled = false + + f.RestoreCalled = false + f.FailRestore = nil + f.RestoreDelay = 0 +} + +func (f *FakeAteletServer) Run(ctx context.Context, req *ateletpb.RunRequest) (*ateletpb.RunResponse, error) { + f.Lock.Lock() + defer f.Lock.Unlock() + + f.RunCalled = true + + return &ateletpb.RunResponse{}, nil +} + +func (f *FakeAteletServer) Checkpoint(ctx context.Context, req *ateletpb.CheckpointRequest) (*ateletpb.CheckpointResponse, error) { + f.Lock.Lock() + defer f.Lock.Unlock() + + f.CheckpointCalled = true + + return &ateletpb.CheckpointResponse{}, nil +} + +func (f *FakeAteletServer) Restore(ctx context.Context, req *ateletpb.RestoreRequest) (*ateletpb.RestoreResponse, error) { + f.Lock.Lock() + defer f.Lock.Unlock() + + f.RestoreCalled = true + if f.RestoreDelay > 0 { + time.Sleep(f.RestoreDelay) + } + if f.FailRestore != nil { + return nil, f.FailRestore + } + return &ateletpb.RestoreResponse{}, nil +} + +type testContext struct { + mr *miniredis.Miniredis + service *Service + client ateapipb.ControlClient + k8sClient kubernetes.Interface + substrateClient versioned.Interface + persistence *ateredis.Persistence + fakeAtelet *FakeAteletServer + cleanup func() + actorTemplateLister listersv1alpha1.ActorTemplateLister +} + +// setupTest sets up a fully isolated test environment. +func setupTest(t *testing.T, ns string) *testContext { + t.Helper() + // 1. Start Miniredis + mr, err := miniredis.Run() + if err != nil { + t.Fatalf("failed to start miniredis: %v", err) + } + + rdb := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{mr.Addr()}, + }) + persistence := ateredis.NewPersistence(rdb) + + // 2. Initialize Clientsets using global cfg + k8sClient, err := kubernetes.NewForConfig(cfg) + if err != nil { + mr.Close() + t.Fatalf("failed to create k8s clientset: %v", err) + } + + substrateClient, err := versioned.NewForConfig(cfg) + if err != nil { + mr.Close() + t.Fatalf("failed to create substrate clientset: %v", err) + } + + // 3. Initialize Informers + workerFactory, workerInformer := WorkerPodInformer(k8sClient) + ateletFactory, ateletInformer := AteletInformer(k8sClient) + + substrateInformerFactory := externalversions.NewSharedInformerFactory(substrateClient, 0) + actorTemplateLister := substrateInformerFactory.Api().V1alpha1().ActorTemplates().Lister() + + ctx, cancel := context.WithCancel(context.Background()) + + syncer := NewWorkerPoolSyncer(persistence, workerInformer) + syncer.Start(ctx) + + workerFactory.Start(ctx.Done()) + ateletFactory.Start(ctx.Done()) + substrateInformerFactory.Start(ctx.Done()) + + workerFactory.WaitForCacheSync(ctx.Done()) + ateletFactory.WaitForCacheSync(ctx.Done()) + substrateInformerFactory.WaitForCacheSync(ctx.Done()) + + // 4. Initialize Service + dialer := NewAteletDialer(workerInformer.GetIndexer(), ateletInformer.GetIndexer()) + service := NewService(persistence, actorTemplateLister, dialer) + + // 5. Start REAL gRPC Server for ATE API + grpcServer := grpc.NewServer(grpc.UnaryInterceptor(StatusErrorInterceptor)) + ateapipb.RegisterControlServer(grpcServer, service) + + lis, err := net.Listen("tcp", "localhost:0") + if err != nil { + cancel() + mr.Close() + t.Fatalf("failed to listen: %v", err) + } + + go func() { + if err := grpcServer.Serve(lis); err != nil { + t.Logf("grpc server exited: %v", err) + } + }() + + conn, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + grpcServer.Stop() + cancel() + mr.Close() + t.Fatalf("failed to connect: %v", err) + } + + client := ateapipb.NewControlClient(conn) + + // Call Reset on global mock + fakeAtelet.Reset() + + // Create namespace + _, err = k8sClient.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: ns}, + }, metav1.CreateOptions{}) + if err != nil { + conn.Close() + grpcServer.Stop() + cancel() + mr.Close() + t.Fatalf("failed to create namespace %s: %v", ns, err) + } + + cleanup := func() { + conn.Close() + grpcServer.Stop() + cancel() + mr.Close() + } + + return &testContext{ + mr: mr, + service: service, + client: client, + k8sClient: k8sClient, + substrateClient: substrateClient, + persistence: persistence, + fakeAtelet: fakeAtelet, + cleanup: cleanup, + actorTemplateLister: actorTemplateLister, + } +} + +func namespaceForTest(baseName string) string { + return fmt.Sprintf("%s-%d", baseName, time.Now().UnixNano()) +} + +func createTemplate(t *testing.T, tc *testContext, ns string) { + t.Helper() + actorTemplate := &atev1alpha1.ActorTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: "tmpl1", + Namespace: ns, + }, + Spec: atev1alpha1.ActorTemplateSpec{ + Runsc: atev1alpha1.RunscConfig{ + AMD64: &atev1alpha1.RunscPlatformConfig{ + URL: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc", + SHA256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63", + }, + }, + PauseImage: "pause", + Containers: []atev1alpha1.Container{ + { + Name: "main", + Image: "main", + Command: []string{"/main"}, + }, + }, + WorkerPoolRef: corev1.ObjectReference{ + Namespace: ns, + Name: "pool1", + }, + }, + } + createdTemplate, err := tc.substrateClient.ApiV1alpha1().ActorTemplates(ns).Create(context.Background(), actorTemplate, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("failed to create actor template: %v", err) + } + + createdTemplate.Status = atev1alpha1.ActorTemplateStatus{ + GoldenSnapshot: "gs://my-bucket/my-folder", + } + + _, err = tc.substrateClient.ApiV1alpha1().ActorTemplates(ns).UpdateStatus(context.Background(), createdTemplate, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("failed to update status: %v", err) + } + + // Wait for Informer cache to sync + err = wait.PollUntilContextTimeout(context.Background(), 100*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) { + tmpl, err := tc.actorTemplateLister.ActorTemplates(ns).Get("tmpl1") + if err != nil { + return false, nil // Retry if not found in cache yet + } + return tmpl.Status.GoldenSnapshot != "", nil + }) + if err != nil { + t.Fatalf("failed to wait for template status update in informer: %v", err) + } +} + +func createWorkerPod(t *testing.T, tc *testContext, ns string, name string, nodeName string) { + t.Helper() + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + Labels: map[string]string{ + "ate.dev/worker-pool": "pool1", + }, + }, + Spec: corev1.PodSpec{ + NodeName: nodeName, + Containers: []corev1.Container{ + {Name: "main", Image: "nginx"}, + }, + }, + } + createdPod, err := tc.k8sClient.CoreV1().Pods(ns).Create(context.Background(), pod, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("failed to create worker pod: %v", err) + } + createdPod.Status.PodIPs = []corev1.PodIP{{IP: "127.0.0.1"}} + createdPod.Status.Phase = corev1.PodRunning + _, err = tc.k8sClient.CoreV1().Pods(ns).UpdateStatus(context.Background(), createdPod, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("failed to update worker pod status: %v", err) + } + + // Wait for worker to be registered via API + err = wait.PollUntilContextTimeout(context.Background(), 100*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) { + resp, err := tc.client.ListWorkers(ctx, &ateapipb.ListWorkersRequest{}) + if err != nil { + return false, nil // Retry on API error + } + for _, w := range resp.GetWorkers() { + if w.GetWorkerNamespace() == ns && w.GetWorkerPod() == name { + return true, nil + } + } + return false, nil + }) + if err != nil { + t.Fatalf("failed to wait for worker to be registered: %v", err) + } +} + +func deleteWorkerPod(t *testing.T, tc *testContext, ns string, name string) { + t.Helper() + err := tc.k8sClient.CoreV1().Pods(ns).Delete(context.Background(), name, metav1.DeleteOptions{}) + if err != nil { + t.Fatalf("failed to delete worker pod %s: %v", name, err) + } + + // Wait for worker to be removed from API + err = wait.PollUntilContextTimeout(context.Background(), 100*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (bool, error) { + resp, err := tc.client.ListWorkers(ctx, &ateapipb.ListWorkersRequest{}) + if err != nil { + return false, nil // Retry on API error + } + for _, w := range resp.GetWorkers() { + if w.GetWorkerNamespace() == ns && w.GetWorkerPod() == name { + return false, nil // Still there + } + } + return true, nil // Gone! + }) + if err != nil { + t.Fatalf("failed to wait for worker to be removed: %v", err) + } +} + +// TestCreateActor_Success tests the happy path for creating an actor. +// Workflow: +// 1. Creates a mock ActorTemplate in the test namespace. +// 2. Calls CreateActor RPC. +// 3. Verifies that the actor is successfully created and returned in the response with a generated ID. +func TestCreateActor_Success(t *testing.T) { + ns := namespaceForTest("ns-create-success") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + createResp, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + want := &ateapipb.CreateActorResponse{ + Actor: &ateapipb.Actor{ + ActorId: "id1", + Version: 1, + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + Status: ateapipb.Actor_STATUS_SUSPENDED, + }, + } + + if diff := cmp.Diff(want, createResp, protocmp.Transform()); diff != "" { + t.Errorf("CreateActor response mismatch (-want +got):\n%s", diff) + } +} + +// TestCreateActor_TemplateNotFound tests that creating an actor with a non-existent template fails with FailedPrecondition. +func TestCreateActor_TemplateNotFound(t *testing.T) { + ns := namespaceForTest("ns-create-notfound") + tc := setupTest(t, ns) + defer tc.cleanup() + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "non-existent", + ActorId: "id1", + }) + assertGrpcError(t, err, codes.FailedPrecondition, fmt.Sprintf("ActorTemplate %s/non-existent not found", ns)) +} + +// TestCreateActor_Duplicate tests that creating an actor with an existing ID fails. +func TestCreateActor_Duplicate(t *testing.T) { + ns := namespaceForTest("ns-create-dup") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("first CreateActor failed: %v", err) + } + + _, err = tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + assertGrpcError(t, err, codes.AlreadyExists, "Actor id1 already exists") +} + +// TestGetActor_Found tests that an existing actor can be retrieved. +func TestGetActor_Found(t *testing.T) { + ns := namespaceForTest("ns-get-found") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + createResp, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + id := createResp.GetActor().GetActorId() + + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + + want := &ateapipb.GetActorResponse{ + Actor: createResp.GetActor(), + } + + if diff := cmp.Diff(want, getResp, protocmp.Transform()); diff != "" { + t.Errorf("GetActor response mismatch (-want +got):\n%s", diff) + } +} + +// TestGetActor_NotFound tests that retrieving a non-existent actor fails. +// Workflow: +// 1. Calls GetActor RPC with a non-existent ID. +// 2. Verifies that it returns an error (NotFound). +func TestGetActor_NotFound(t *testing.T) { + ns := namespaceForTest("ns-get-notfound") + tc := setupTest(t, ns) + defer tc.cleanup() + + _, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: "non-existent", + }) + assertGrpcError(t, err, codes.NotFound, "Actor non-existent not found") +} + +// TestListActors tests that all created actors can be listed. +// Workflow: +// 1. Creates a mock ActorTemplate. +// 2. Calls CreateActor twice to create two actors. +// 3. Calls ListActors RPC. +// 4. Verifies that both actors are returned in the list. +func TestListActors(t *testing.T) { + ns := namespaceForTest("ns-list-actors") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + resp1, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor 1 failed: %v", err) + } + resp2, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id2", + }) + if err != nil { + t.Fatalf("CreateActor 2 failed: %v", err) + } + + listResp, err := tc.client.ListActors(context.Background(), &ateapipb.ListActorsRequest{}) + if err != nil { + t.Fatalf("ListActors failed: %v", err) + } + + if len(listResp.Actors) != 2 { + t.Fatalf("expected 2 actors, got %d", len(listResp.Actors)) + } + + sort.Slice(listResp.Actors, func(i, j int) bool { + return listResp.Actors[i].ActorId < listResp.Actors[j].ActorId + }) + + want := []*ateapipb.Actor{ + resp1.GetActor(), + resp2.GetActor(), + } + sort.Slice(want, func(i, j int) bool { + return want[i].ActorId < want[j].ActorId + }) + + if diff := cmp.Diff(want, listResp.Actors, protocmp.Transform()); diff != "" { + t.Errorf("ListActors response mismatch (-want +got):\n%s", diff) + } +} + +// TestListWorkers tests that workers mirrored to Redis are listed. +// Workflow: +// 1. Creates a mock worker Pod in Kubernetes. +// 2. Waits for the background WorkerPoolSyncer to mirror it to Redis. +// 3. Calls ListWorkers RPC. +// 4. Verifies that the worker appears in the response. +func TestListWorkers(t *testing.T) { + ns := namespaceForTest("ns-list-workers") + tc := setupTest(t, ns) + defer tc.cleanup() + + createWorkerPod(t, tc, ns, "worker-1", "") + + listResp, err := tc.client.ListWorkers(context.Background(), &ateapipb.ListWorkersRequest{}) + if err != nil { + t.Fatalf("ListWorkers failed: %v", err) + } + + var filteredWorkers []*ateapipb.Worker + for _, w := range listResp.GetWorkers() { + if w.GetWorkerNamespace() == ns { + filteredWorkers = append(filteredWorkers, w) + } + } + + want := []*ateapipb.Worker{ + { + WorkerNamespace: ns, + WorkerPool: "pool1", + WorkerPod: "worker-1", + Ip: "127.0.0.1", + Version: 1, + }, + } + + if diff := cmp.Diff(want, filteredWorkers, protocmp.Transform()); diff != "" { + t.Errorf("ListWorkers response mismatch (-want +got):\n%s", diff) + } +} + +// TestResumeActor tests the full workflow of resuming a suspended actor. +// Workflow: +// 1. Creates a mock ActorTemplate. +// 2. Creates a mock Atelet Pod in 'ate-system' namespace on 'node1'. +// 3. Creates a mock worker Pod in the test namespace on 'node1'. +// 4. Waits for the WorkerPoolSyncer to mirror the worker to Redis. +// 5. Creates an actor (starts as SUSPENDED). +// 6. Calls ResumeActor RPC. +// 7. Verifies that the fake Atelet received the Restore call. +// 8. Verifies that the actor status is updated to RUNNING. +func TestResumeActor(t *testing.T) { + ns := namespaceForTest("ns-resume") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + createWorkerPod(t, tc, ns, "worker-1", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + id := "id1" + + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("ResumeActor failed: %v", err) + } + + if !tc.fakeAtelet.RestoreCalled { + t.Errorf("expected Restore to be called") + } + + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + want := &ateapipb.GetActorResponse{ + Actor: &ateapipb.Actor{ + ActorId: id, + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + Status: ateapipb.Actor_STATUS_RUNNING, + AteomPodNamespace: ns, + AteomPodName: "worker-1", + AteomPodIp: "127.0.0.1", + }, + } + if diff := cmp.Diff(want, getResp, protocmp.Transform(), protocmp.IgnoreFields(&ateapipb.Actor{}, "version")); diff != "" { + t.Errorf("GetActor response mismatch (-want +got):\n%s", diff) + } + + // Verify that the worker record also has the assigned actor details + listWorkersResp, err := tc.client.ListWorkers(context.Background(), &ateapipb.ListWorkersRequest{}) + if err != nil { + t.Fatalf("ListWorkers failed: %v", err) + } + var actorWorker *ateapipb.Worker + for _, w := range listWorkersResp.GetWorkers() { + if w.GetWorkerNamespace() == ns && w.GetWorkerPod() == "worker-1" { + actorWorker = w + break + } + } + if actorWorker == nil { + t.Fatalf("expected worker-1 in namespace %s not found in ListWorkers", ns) + } + + wantWorker := &ateapipb.Worker{ + WorkerNamespace: ns, + WorkerPool: "pool1", + WorkerPod: "worker-1", + ActorNamespace: ns, + ActorTemplate: "tmpl1", + ActorId: id, + Ip: "127.0.0.1", + } + + if diff := cmp.Diff(wantWorker, actorWorker, protocmp.Transform(), protocmp.IgnoreFields(&ateapipb.Worker{}, "version")); diff != "" { + t.Errorf("Worker state mismatch (-want +got):\n%s", diff) + } +} + +// TestResumeActor_NoWorkers tests that resuming an actor fails when no free workers are available. +// Workflow: +// 1. Creates a mock ActorTemplate. +// 2. Creates an actor. +// 3. Calls ResumeActor RPC without creating any workers. +// 4. Verifies that ResumeActor fails with FailedPrecondition status. +// TestResumeActor_NoWorkers tests that resuming an actor fails when no free workers are available. +// Workflow: +// 1. Creates a mock ActorTemplate. +// 2. Creates an actor. +// 3. Calls ResumeActor RPC without creating any workers. +// 4. Verifies that ResumeActor fails with FailedPrecondition status. +func TestResumeActor_NoWorkers(t *testing.T) { + ns := namespaceForTest("ns-resume-no-workers") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + createResp, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + id := createResp.GetActor().GetActorId() + + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + assertGrpcError(t, err, codes.FailedPrecondition, "no free workers available") +} + +// TestResumeActor_Reentrancy tests the failure recovery and re-entrancy of ResumeActor. +// Workflow: +// 1. Creates a mock ActorTemplate. +// 2. Creates a mock Atelet Pod and a mock Worker Pod. +// 3. Waits for the WorkerPoolSyncer to mirror the worker to store. +// 4. Creates an actor in SUSPENDED state. +// 5. Configures fake Atelet to FAIL on Restore. +// 6. Calls ResumeActor and verifies it fails, but actor status becomes RESUMING. +// 7. Configures fake Atelet to SUCCEED on Restore. +// 8. Calls ResumeActor again and verifies it succeeds and actor status becomes RUNNING. +func TestResumeActor_Reentrancy(t *testing.T) { + ns := namespaceForTest("ns-resume-reentrancy") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + // Create Worker Pod + createWorkerPod(t, tc, ns, "worker-1", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + id := "id1" + + // STEP 1: Make Atelet FAIL on Restore! + tc.fakeAtelet.FailRestore = fmt.Errorf("mock atelet failure") + + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err == nil { + t.Fatalf("expected ResumeActor to fail due to atelet error") + } + + // Verify actor state is RESUMING in Redis! + actor, err := tc.persistence.GetActor(context.Background(), id) + if err != nil { + t.Fatalf("failed to get actor from store: %v", err) + } + if actor.GetStatus() != ateapipb.Actor_STATUS_RESUMING { + t.Errorf("expected status RESUMING, got %v", actor.GetStatus()) + } + + // STEP 2: Make Atelet SUCCEED! + tc.fakeAtelet.FailRestore = nil + tc.fakeAtelet.RestoreCalled = false // reset for verification + + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("ResumeActor failed on retry: %v", err) + } + + if !tc.fakeAtelet.RestoreCalled { + t.Errorf("expected Restore to be called on retry") + } + + // Verify actor state is RUNNING! + actor, err = tc.persistence.GetActor(context.Background(), id) + if err != nil { + t.Fatalf("failed to get actor from store: %v", err) + } + if actor.GetStatus() != ateapipb.Actor_STATUS_RUNNING { + t.Errorf("expected status RUNNING, got %v", actor.GetStatus()) + } +} + +// TestSuspendActor tests the full workflow of suspending a running actor. +// Workflow: +// 1. Creates a mock ActorTemplate. +// 2. Creates a mock Atelet Pod on 'node1'. +// 3. Creates a mock worker Pod on 'node1'. +// 4. Waits for the WorkerPoolSyncer to mirror the worker to Redis. +// 5. Creates an actor. +// 6. Calls ResumeActor to transition it to RUNNING. +// 7. Calls SuspendActor RPC. +// 8. Verifies that the fake Atelet received the Suspend call. +func TestSuspendActor(t *testing.T) { + ns := namespaceForTest("ns-suspend") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + createWorkerPod(t, tc, ns, "worker-1", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + id := "id1" + + // Resume first to make it running + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("ResumeActor failed: %v", err) + } + + // Suspend + _, err = tc.client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("SuspendActor failed: %v", err) + } + + if !tc.fakeAtelet.CheckpointCalled { + t.Errorf("expected atelet Checkpoint to be called") + } + + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + want := &ateapipb.GetActorResponse{ + Actor: &ateapipb.Actor{ + ActorId: id, + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + Status: ateapipb.Actor_STATUS_SUSPENDED, + LastSnapshot: fmt.Sprintf("gs://my-bucket/%s/tmpl1/%s/", ns, id), + }, + } + + if diff := cmp.Diff(want, getResp, protocmp.Transform(), protocmp.IgnoreFields(&ateapipb.Actor{}, "version"), protocmp.IgnoreFields(&ateapipb.Actor{}, "last_snapshot")); diff != "" { + t.Errorf("GetActor response mismatch (-want +got):\n%s", diff) + } + +} + +// TestValidation tests the negative validation cases for all gRPC methods. +// Workflow: +// 1. Uses table-driven tests for each RPC method (CreateActor, GetActor, ResumeActor, SuspendActor). +// 2. Passes invalid requests (missing required fields). +// 3. Verifies that all requests fail with an error. +func TestValidation(t *testing.T) { + ns := namespaceForTest("ns-validation") + tc := setupTest(t, ns) + defer tc.cleanup() + + t.Run("CreateActor", func(t *testing.T) { + tests := []struct { + name string + req *ateapipb.CreateActorRequest + wantMsg string + }{ + {"missing namespace", &ateapipb.CreateActorRequest{ActorTemplateName: "tmpl1", ActorId: "id1"}, "actor_template_namespace is required"}, + {"missing template name", &ateapipb.CreateActorRequest{ActorTemplateNamespace: "ns1", ActorId: "id1"}, "actor_template_name is required"}, + {"missing actor id", &ateapipb.CreateActorRequest{ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1"}, "actor_id is required"}, + {"invalid actor id (capitals)", &ateapipb.CreateActorRequest{ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1", ActorId: "ID1"}, "invalid actor_id: must start and end with a lower case alphanumeric character, and consist only of lower case alphanumeric characters or '-'"}, + {"invalid actor id (special chars)", &ateapipb.CreateActorRequest{ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1", ActorId: "id_1"}, "invalid actor_id: must start and end with a lower case alphanumeric character, and consist only of lower case alphanumeric characters or '-'"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := tc.client.CreateActor(context.Background(), tt.req) + assertGrpcError(t, err, codes.InvalidArgument, tt.wantMsg) + }) + } + }) + + t.Run("GetActor", func(t *testing.T) { + tests := []struct { + name string + req *ateapipb.GetActorRequest + wantMsg string + }{ + {"missing id", &ateapipb.GetActorRequest{}, "id is required"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := tc.client.GetActor(context.Background(), tt.req) + assertGrpcError(t, err, codes.InvalidArgument, tt.wantMsg) + }) + } + }) + + t.Run("ResumeActor", func(t *testing.T) { + tests := []struct { + name string + req *ateapipb.ResumeActorRequest + wantMsg string + }{ + {"missing id", &ateapipb.ResumeActorRequest{}, "id is required"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := tc.client.ResumeActor(context.Background(), tt.req) + assertGrpcError(t, err, codes.InvalidArgument, tt.wantMsg) + }) + } + }) + + t.Run("SuspendActor", func(t *testing.T) { + tests := []struct { + name string + req *ateapipb.SuspendActorRequest + wantMsg string + }{ + {"missing id", &ateapipb.SuspendActorRequest{}, "id is required"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := tc.client.SuspendActor(context.Background(), tt.req) + assertGrpcError(t, err, codes.InvalidArgument, tt.wantMsg) + }) + } + }) + + t.Run("DeleteActor", func(t *testing.T) { + tests := []struct { + name string + req *ateapipb.DeleteActorRequest + wantMsg string + }{ + {"missing id", &ateapipb.DeleteActorRequest{}, "actor_id is required"}, + {"invalid actor id (capitals)", &ateapipb.DeleteActorRequest{ActorId: "ID1"}, "invalid actor_id: must start and end with a lower case alphanumeric character, and consist only of lower case alphanumeric characters or '-'"}, + {"invalid actor id (special chars)", &ateapipb.DeleteActorRequest{ActorId: "id_1"}, "invalid actor_id: must start and end with a lower case alphanumeric character, and consist only of lower case alphanumeric characters or '-'"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := tc.client.DeleteActor(context.Background(), tt.req) + assertGrpcError(t, err, codes.InvalidArgument, tt.wantMsg) + }) + } + }) +} + +func TestResumeActor_LockConflict(t *testing.T) { + ns := namespaceForTest("ns-resume-conflict") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + createWorkerPod(t, tc, ns, "worker-1", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + id := "id1" + + // Set a delay on the fake Atelet to hold the lock + tc.fakeAtelet.RestoreDelay = 1 * time.Second + + // Launch Request A in a goroutine + errChan := make(chan error, 1) + go func() { + _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + errChan <- err + }() + + // Sleep a bit to ensure Request A acquired the lock + time.Sleep(200 * time.Millisecond) + + // Launch Request B (should fail due to lock conflict) + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + assertGrpcError(t, err, codes.Aborted, "another operation is in progress for this actor") + + // Wait for Request A to finish + if errA := <-errChan; errA != nil { + t.Fatalf("Request A failed: %v", errA) + } +} + +func TestResumeActor_DanglingWorker(t *testing.T) { + ns := namespaceForTest("ns-resume-dangling") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + // 1. Create Worker Pod A + createWorkerPod(t, tc, ns, "worker-a", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + id := "id1" + + // 2. Configure fake Atelet to FAIL on Restore! + tc.fakeAtelet.FailRestore = fmt.Errorf("mock atelet failure") + + // 3. Call ResumeActor -> Expect failure + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err == nil { + t.Fatalf("expected ResumeActor to fail due to atelet error") + } + + // Verify actor state is RESUMING with worker A assigned + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + actor := getResp.GetActor() + if actor.GetStatus() != ateapipb.Actor_STATUS_RESUMING { + t.Fatalf("expected status RESUMING, got %v", actor.GetStatus()) + } + if actor.GetAteomPodName() != "worker-a" { + t.Fatalf("expected worker-a assigned, got %v", actor.GetAteomPodName()) + } + + deleteWorkerPod(t, tc, ns, "worker-a") + + // 6. Create Worker Pod B + createWorkerPod(t, tc, ns, "worker-b", "node1") + + // 7. Configure fake Atelet to SUCCEED on Restore + tc.fakeAtelet.FailRestore = nil + tc.fakeAtelet.RestoreCalled = false // reset + + // 8. Call ResumeActor again -> Expect success and picking Worker B! + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("ResumeActor failed on retry: %v", err) + } + + if !tc.fakeAtelet.RestoreCalled { + t.Errorf("expected Restore to be called on retry") + } + + // Verify actor state is RUNNING with worker B assigned + actor, err = tc.persistence.GetActor(context.Background(), id) + if err != nil { + t.Fatalf("failed to get actor from store: %v", err) + } + if actor.GetStatus() != ateapipb.Actor_STATUS_RUNNING { + t.Errorf("expected status RUNNING, got %v", actor.GetStatus()) + } + if actor.GetAteomPodName() != "worker-b" { + t.Errorf("expected worker-b assigned, got %v", actor.GetAteomPodName()) + } +} + +func TestSuspendActor_DanglingWorker(t *testing.T) { + ns := namespaceForTest("ns-sd") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + // 1. Create Worker Pod + createWorkerPod(t, tc, ns, "worker-1", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + id := "id1" + + // Resume first to make it running + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("ResumeActor failed: %v", err) + } + + deleteWorkerPod(t, tc, ns, "worker-1") + + // 3. Call SuspendActor -> Should succeed (our fix skips missing pod execution) + actors, _ := tc.persistence.ListActors(context.Background()) + t.Logf("Actors in Redis before Suspend: %d", len(actors)) + for _, a := range actors { + t.Logf(" Actor: %s/%s/%s", a.GetActorTemplateNamespace(), a.GetActorTemplateName(), a.GetActorId()) + } + + _, err = tc.client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("SuspendActor failed: %v", err) + } + + // 4. Verify it becomes SUSPENDED in Redis + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: id, + }) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + if getResp.GetActor().GetStatus() != ateapipb.Actor_STATUS_SUSPENDED { + t.Errorf("expected status SUSPENDED, got %v", getResp.GetActor().GetStatus()) + } + if getResp.GetActor().GetAteomPodNamespace() != "" { + t.Errorf("expected ateom_pod_namespace to be empty, got %v", getResp.GetActor().GetAteomPodNamespace()) + } +} + +func TestDeleteActor_Success(t *testing.T) { + ns := namespaceForTest("ns-delete-success") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + _, err = tc.client.DeleteActor(context.Background(), &ateapipb.DeleteActorRequest{ + ActorId: "id1", + }) + if err != nil { + t.Fatalf("DeleteActor failed: %v", err) + } + + _, err = tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ + ActorId: "id1", + }) + assertGrpcError(t, err, codes.NotFound, "Actor id1 not found") +} + +func TestDeleteActor_NotSuspended(t *testing.T) { + ns := namespaceForTest("ns-delete-notsuspended") + tc := setupTest(t, ns) + defer tc.cleanup() + + createTemplate(t, tc, ns) + createWorkerPod(t, tc, ns, "worker-1", "node1") + + _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ + ActorTemplateNamespace: ns, + ActorTemplateName: "tmpl1", + ActorId: "id1", + }) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ + ActorId: "id1", + }) + if err != nil { + t.Fatalf("ResumeActor failed: %v", err) + } + + _, err = tc.client.DeleteActor(context.Background(), &ateapipb.DeleteActorRequest{ + ActorId: "id1", + }) + assertGrpcError(t, err, codes.FailedPrecondition, "Actor id1 is not suspended (status: STATUS_RUNNING)") +} + +func TestDeleteActor_NotFound(t *testing.T) { + ns := namespaceForTest("ns-delete-notfound") + tc := setupTest(t, ns) + defer tc.cleanup() + + _, err := tc.client.DeleteActor(context.Background(), &ateapipb.DeleteActorRequest{ + ActorId: "non-existent", + }) + assertGrpcError(t, err, codes.NotFound, "Actor non-existent not found") +} + +func assertGrpcError(t *testing.T, err error, wantCode codes.Code, wantMsg string) { + t.Helper() + if err == nil { + t.Fatalf("expected error, got nil") + } + st, ok := status.FromError(err) + if !ok { + t.Fatalf("expected gRPC status error, got: %v", err) + } + if st.Code() != wantCode { + t.Errorf("expected status %v, got %v", wantCode, st.Code()) + } + if st.Message() != wantMsg { + t.Errorf("expected message %q, got %q", wantMsg, st.Message()) + } +} diff --git a/cmd/servers/ateapi/controlapi/get_actor.go b/cmd/servers/ateapi/controlapi/get_actor.go new file mode 100644 index 000000000..292cd69e5 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/get_actor.go @@ -0,0 +1,48 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "fmt" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) GetActor(ctx context.Context, req *ateapipb.GetActorRequest) (*ateapipb.GetActorResponse, error) { + if err := validateGetActorRequest(req); err != nil { + return nil, err + } + actor, err := s.persistence.GetActor(ctx, req.GetActorId()) + if errors.Is(err, store.ErrNotFound) { + return nil, status.Errorf(codes.NotFound, "Actor %s not found", req.GetActorId()) + } else if err != nil { + return nil, fmt.Errorf("while getting actor from DB: %w", err) + } + return &ateapipb.GetActorResponse{ + Actor: actor, + }, nil +} + +func validateGetActorRequest(req *ateapipb.GetActorRequest) error { + if req.GetActorId() == "" { + return status.Error(codes.InvalidArgument, "id is required") + } + return nil +} diff --git a/cmd/servers/ateapi/controlapi/informer.go b/cmd/servers/ateapi/controlapi/informer.go new file mode 100644 index 000000000..98b9cca8d --- /dev/null +++ b/cmd/servers/ateapi/controlapi/informer.go @@ -0,0 +1,75 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/cache" +) + +const ( + ateletNamespace = "ate-system" + byNamespaceAndName = "by-namespace-and-name" + byWorkerPool = "by-worker-pool" + byNode = "by-node" + workerPodLabel = "ate.dev/worker-pool" +) + +// AteletInformer creates a SharedInformerFactory and SharedIndexInformer for Atelet pods. +func AteletInformer(kc kubernetes.Interface) (informers.SharedInformerFactory, cache.SharedIndexInformer) { + factory := informers.NewSharedInformerFactoryWithOptions(kc, 0, + informers.WithNamespace(ateletNamespace), + informers.WithTweakListOptions(func(options *metav1.ListOptions) { + options.LabelSelector = `app in (atelet)` + }), + ) + ateletInformer := factory.Core().V1().Pods().Informer() + ateletInformer.AddIndexers(cache.Indexers{ + byNode: func(obj any) ([]string, error) { + pod := obj.(*corev1.Pod) + return []string{pod.Spec.NodeName}, nil + }, + }) + return factory, ateletInformer +} + +// WorkerPodInformer creates a SharedInformerFactory and SharedIndexInformer for Worker pods. +func WorkerPodInformer(kc kubernetes.Interface) (informers.SharedInformerFactory, cache.SharedIndexInformer) { + factory := informers.NewSharedInformerFactoryWithOptions(kc, 5*time.Minute, + informers.WithTweakListOptions(func(options *metav1.ListOptions) { + options.LabelSelector = "ate.dev/worker-pool" + }), + ) + workerPodInformer := factory.Core().V1().Pods().Informer() + workerPodInformer.AddIndexers(cache.Indexers{ + byNamespaceAndName: func(obj any) ([]string, error) { + pod := obj.(*corev1.Pod) + key := pod.ObjectMeta.Namespace + "/" + pod.ObjectMeta.Name + return []string{key}, nil + }, + byWorkerPool: func(obj any) ([]string, error) { + pod := obj.(*corev1.Pod) + workerPoolRef := pod.ObjectMeta.Namespace + "/" + pod.ObjectMeta.Labels["ate.dev/worker-pool"] + return []string{workerPoolRef}, nil + }, + }) + + return factory, workerPodInformer +} diff --git a/cmd/servers/ateapi/controlapi/list_actors.go b/cmd/servers/ateapi/controlapi/list_actors.go new file mode 100644 index 000000000..8a9f2691b --- /dev/null +++ b/cmd/servers/ateapi/controlapi/list_actors.go @@ -0,0 +1,39 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "fmt" + + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +func (s *Service) ListActors(ctx context.Context, req *ateapipb.ListActorsRequest) (*ateapipb.ListActorsResponse, error) { + if err := validateListActorsRequest(req); err != nil { + return nil, err + } + actors, err := s.persistence.ListActors(ctx) + if err != nil { + return nil, fmt.Errorf("while listing actors in db: %w", err) + } + return &ateapipb.ListActorsResponse{ + Actors: actors, + }, nil +} + +func validateListActorsRequest(_ *ateapipb.ListActorsRequest) error { + return nil +} diff --git a/cmd/servers/ateapi/controlapi/list_workers.go b/cmd/servers/ateapi/controlapi/list_workers.go new file mode 100644 index 000000000..b427338f0 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/list_workers.go @@ -0,0 +1,40 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "fmt" + + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +func (s *Service) ListWorkers(ctx context.Context, req *ateapipb.ListWorkersRequest) (*ateapipb.ListWorkersResponse, error) { + if err := validateListWorkersRequest(req); err != nil { + return nil, err + } + workers, err := s.persistence.ListWorkers(ctx) + if err != nil { + return nil, fmt.Errorf("while listing workers in db: %w", err) + } + return &ateapipb.ListWorkersResponse{ + Workers: workers, + }, nil +} + +func validateListWorkersRequest(_ *ateapipb.ListWorkersRequest) error { + // No fields to validate for now. + return nil +} diff --git a/cmd/servers/ateapi/controlapi/resume_actor.go b/cmd/servers/ateapi/controlapi/resume_actor.go new file mode 100644 index 000000000..3410b5167 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/resume_actor.go @@ -0,0 +1,51 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) ResumeActor(ctx context.Context, req *ateapipb.ResumeActorRequest) (*ateapipb.ResumeActorResponse, error) { + if err := validateResumeActorRequest(req); err != nil { + return nil, err + } + + actor, err := s.actorWorkflow.ResumeActor(ctx, req.GetActorId(), req.GetBoot()) + if err != nil { + if errors.Is(err, store.ErrPersistenceRetry) { + return nil, status.Error(codes.Aborted, "concurrent update conflict, please retry") + } + if errors.Is(err, store.ErrNotFound) { + return nil, status.Errorf(codes.NotFound, "Actor %s not found", req.GetActorId()) + } + return nil, err + } + + return &ateapipb.ResumeActorResponse{Actor: actor}, nil +} + +func validateResumeActorRequest(req *ateapipb.ResumeActorRequest) error { + if req.GetActorId() == "" { + return status.Error(codes.InvalidArgument, "id is required") + } + return nil +} diff --git a/cmd/servers/ateapi/controlapi/service.go b/cmd/servers/ateapi/controlapi/service.go new file mode 100644 index 000000000..9afd6ac17 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/service.go @@ -0,0 +1,74 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "log/slog" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + listersv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// Service implements ateapipb.Control +type Service struct { + ateapipb.UnimplementedControlServer + persistence store.Interface + dialer *AteletDialer + actorTemplateLister listersv1alpha1.ActorTemplateLister + actorWorkflow *ActorWorkflow +} + +var _ ateapipb.ControlServer = (*Service)(nil) + +// NewService creates a service. +func NewService(persistence store.Interface, actorTemplateLister listersv1alpha1.ActorTemplateLister, dialer *AteletDialer) *Service { + s := &Service{ + persistence: persistence, + actorTemplateLister: actorTemplateLister, + dialer: dialer, + actorWorkflow: NewActorWorkflow(persistence, dialer, actorTemplateLister), + } + + return s +} + +// StatusErrorInterceptor searches the error chain for a gRPC status error. +// If found, it extracts the code and message to send to the client, ignoring +// any outer wrapping, while logging the full error chain internally. +func StatusErrorInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + resp, err := handler(ctx, req) + if err != nil { + var statusErr interface { + GRPCStatus() *status.Status + } + + if errors.As(err, &statusErr) { + st := statusErr.GRPCStatus() + slog.ErrorContext(ctx, "gRPC Error", slog.String("method", info.FullMethod), slog.Any("err", err)) + return nil, status.Error(st.Code(), st.Message()) + } + + slog.ErrorContext(ctx, "Unexpected error", slog.String("method", info.FullMethod), slog.Any("err", err)) + return nil, status.Error(codes.Internal, "internal server error") + } + return resp, nil +} diff --git a/cmd/servers/ateapi/controlapi/service_test.go b/cmd/servers/ateapi/controlapi/service_test.go new file mode 100644 index 000000000..3393670ae --- /dev/null +++ b/cmd/servers/ateapi/controlapi/service_test.go @@ -0,0 +1,90 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package controlapi + +import ( + "context" + "errors" + "fmt" + "testing" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestStatusErrorInterceptor(t *testing.T) { + tests := []struct { + name string + handlerErr error + wantCode codes.Code + wantMsg string + expectResponse bool + }{ + { + name: "Success", + handlerErr: nil, + expectResponse: true, + }, + { + name: "StatusErrorInChain", + handlerErr: fmt.Errorf("outer error: %w", status.Error(codes.NotFound, "actor not found")), + wantCode: codes.NotFound, + wantMsg: "actor not found", + }, + { + name: "RawErrorFallback", + handlerErr: errors.New("database connection failed"), + wantCode: codes.Internal, + wantMsg: "internal server error", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return "response", tt.handlerErr + } + + resp, err := StatusErrorInterceptor(context.Background(), "request", &grpc.UnaryServerInfo{FullMethod: "/test.Service/Method"}, handler) + + if tt.expectResponse { + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp != "response" { + t.Errorf("expected response 'response', got %v", resp) + } + return + } + + if err == nil { + t.Fatalf("expected error, got nil") + } + + st, ok := status.FromError(err) + if !ok { + t.Fatalf("expected gRPC status error, got: %v", err) + } + + if st.Code() != tt.wantCode { + t.Errorf("expected code %v, got %v", tt.wantCode, st.Code()) + } + + if st.Message() != tt.wantMsg { + t.Errorf("expected message %q, got %q", tt.wantMsg, st.Message()) + } + }) + } +} diff --git a/cmd/servers/ateapi/controlapi/suspend_actor.go b/cmd/servers/ateapi/controlapi/suspend_actor.go new file mode 100644 index 000000000..85886034d --- /dev/null +++ b/cmd/servers/ateapi/controlapi/suspend_actor.go @@ -0,0 +1,51 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) SuspendActor(ctx context.Context, req *ateapipb.SuspendActorRequest) (*ateapipb.SuspendActorResponse, error) { + if err := validateSuspendActorRequest(req); err != nil { + return nil, err + } + + actor, err := s.actorWorkflow.SuspendActor(ctx, req.GetActorId()) + if err != nil { + if errors.Is(err, store.ErrPersistenceRetry) { + return nil, status.Error(codes.Aborted, "concurrent update conflict, please retry") + } + if errors.Is(err, store.ErrNotFound) { + return nil, status.Errorf(codes.NotFound, "Actor %s not found", req.GetActorId()) + } + return nil, err + } + + return &ateapipb.SuspendActorResponse{Actor: actor}, nil +} + +func validateSuspendActorRequest(req *ateapipb.SuspendActorRequest) error { + if req.GetActorId() == "" { + return status.Error(codes.InvalidArgument, "id is required") + } + return nil +} diff --git a/cmd/servers/ateapi/controlapi/syncer.go b/cmd/servers/ateapi/controlapi/syncer.go new file mode 100644 index 000000000..1635cc014 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/syncer.go @@ -0,0 +1,141 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "log/slog" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/proto/ateapipb" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" +) + +// WorkerPoolSyncer reconciles the state of worker pods from Kubernetes Informer +// into the store. +type WorkerPoolSyncer struct { + persistence store.Interface + workerInformer cache.SharedIndexInformer +} + +// NewWorkerPoolSyncer creates a new WorkerPoolSyncer. +func NewWorkerPoolSyncer(persistence store.Interface, workerInformer cache.SharedIndexInformer) *WorkerPoolSyncer { + return &WorkerPoolSyncer{ + persistence: persistence, + workerInformer: workerInformer, + } +} + +// Start starts the background reconciliation loop. +func (s *WorkerPoolSyncer) Start(ctx context.Context) { + s.workerInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + pod := obj.(*corev1.Pod) + s.syncWorkerToStore(ctx, pod) + }, + UpdateFunc: func(oldObj, newObj interface{}) { + pod := newObj.(*corev1.Pod) + s.syncWorkerToStore(ctx, pod) + }, + DeleteFunc: func(obj interface{}) { + var pod *corev1.Pod + switch t := obj.(type) { + case *corev1.Pod: + pod = t + case cache.DeletedFinalStateUnknown: + var ok bool + pod, ok = t.Obj.(*corev1.Pod) + if !ok { + slog.ErrorContext(ctx, "Failed to cast DeletedFinalStateUnknown object to Pod") + return + } + default: + slog.ErrorContext(ctx, "Unknown object type in delete handler", slog.Any("obj", obj)) + return + } + slog.InfoContext(ctx, "Syncer: removing worker from store", slog.String("worker", pod.Namespace+"/"+pod.Name)) + err := s.persistence.DeleteWorker(ctx, pod.Namespace, pod.Labels[workerPodLabel], pod.Name) + if err != nil { + slog.ErrorContext(ctx, "Failed to delete worker from store during delete event", slog.Any("err", err)) + } + }, + }) + + go func() { + if !cache.WaitForCacheSync(ctx.Done(), s.workerInformer.HasSynced) { + slog.ErrorContext(ctx, "Syncer: failed to sync informer cache") + return + } + + slog.InfoContext(ctx, "Syncer: performing initial sync on startup") + objs := s.workerInformer.GetIndexer().List() + for _, obj := range objs { + pod := obj.(*corev1.Pod) + s.syncWorkerToStore(ctx, pod) + } + }() +} + +func (s *WorkerPoolSyncer) syncWorkerToStore(ctx context.Context, pod *corev1.Pod) { + if !isWorkerEligible(pod) { + return + } + + if pod.DeletionTimestamp != nil { + slog.InfoContext(ctx, "Syncer: removing worker from store (pod deleting)", slog.String("worker", pod.Namespace+"/"+pod.Name)) + err := s.persistence.DeleteWorker(ctx, pod.Namespace, pod.Labels[workerPodLabel], pod.Name) + if err != nil { + slog.ErrorContext(ctx, "Failed to delete worker from store during update event (deleting)", slog.Any("err", err)) + } + return + } + + w, err := s.persistence.GetWorker(ctx, pod.Namespace, pod.Labels[workerPodLabel], pod.Name) + if err != nil { + if errors.Is(err, store.ErrNotFound) { + slog.InfoContext(ctx, "Syncer: creating worker in store", slog.String("worker", pod.Namespace+"/"+pod.Name)) + err = s.persistence.CreateWorker(ctx, &ateapipb.Worker{ + WorkerNamespace: pod.Namespace, + WorkerPool: pod.Labels[workerPodLabel], + WorkerPod: pod.Name, + Ip: pod.Status.PodIP, + }) + if err != nil && !errors.Is(err, store.ErrAlreadyExists) { + slog.ErrorContext(ctx, "Failed to create worker in store", slog.Any("err", err)) + } + return + } + slog.ErrorContext(ctx, "Failed to get worker from store", slog.Any("err", err)) + return + } + + if w.Ip != pod.Status.PodIP { + // TODO: I don't think this is possible, but handling this case so we can log it just in case we can reproduce it. + slog.InfoContext(ctx, "Syncer: updating worker in store (IP changed)", slog.String("worker", pod.Namespace+"/"+pod.Name)) + w.Ip = pod.Status.PodIP + if err = s.persistence.UpdateWorker(ctx, w, w.Version); err != nil { + slog.ErrorContext(ctx, "Failed to update worker in store", slog.Any("err", err)) + } + } +} + +func isWorkerEligible(pod *corev1.Pod) bool { + if pod.Status.PodIP == "" { + return false + } + return true +} diff --git a/cmd/servers/ateapi/controlapi/syncer_test.go b/cmd/servers/ateapi/controlapi/syncer_test.go new file mode 100644 index 000000000..190d82b05 --- /dev/null +++ b/cmd/servers/ateapi/controlapi/syncer_test.go @@ -0,0 +1,156 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "fmt" + "testing" + "time" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store/storetest" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes/fake" +) + +// setupSyncerTest sets up a real store with fake Redis and a fake K8s client with informer. +func setupSyncerTest(t *testing.T, ctx context.Context) (store.Interface, *fake.Clientset, func()) { + t.Helper() + + persistence, cleanup := storetest.SetupTestStore(t) + + fakeK8s := fake.NewSimpleClientset() + workerFactory, workerInformer := WorkerPodInformer(fakeK8s) + + syncer := NewWorkerPoolSyncer(persistence, workerInformer) + syncer.Start(ctx) + + workerFactory.Start(ctx.Done()) + workerFactory.WaitForCacheSync(ctx.Done()) + + return persistence, fakeK8s, cleanup +} + +func TestSyncer_Lifecycle(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + persistence, fakeK8s, cleanup := setupSyncerTest(t, ctx) + defer cleanup() + + ns := "ns-syncer-lifecycle" + podName := "worker-unit-1" + poolName := "pool1" + + // 1. Verify no workers in Redis initially + workers, err := persistence.ListWorkers(context.Background()) + if err != nil { + t.Fatalf("failed to list workers: %v", err) + } + if len(workers) != 0 { + t.Fatalf("expected 0 workers, got %d", len(workers)) + } + + // 2. Add pod with no IP + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: ns, + Labels: map[string]string{ + workerPodLabel: poolName, + }, + }, + Spec: corev1.PodSpec{ + NodeName: "node1", + Containers: []corev1.Container{ + {Name: "main", Image: "nginx"}, + }, + }, + } + + _, err = fakeK8s.CoreV1().Pods(ns).Create(context.Background(), pod, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("failed to create pod: %v", err) + } + + // 3. Check it's not there (polled for 500ms) + err = wait.PollUntilContextTimeout(context.Background(), 50*time.Millisecond, 500*time.Millisecond, true, func(ctx context.Context) (bool, error) { + _, err := persistence.GetWorker(ctx, ns, poolName, podName) + if err == nil { + return false, fmt.Errorf("worker unexpectedly found in Redis") + } + if !errors.Is(err, store.ErrNotFound) { + return false, err + } + return false, nil // Keep polling + }) + if err != nil { + if !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("Poll failed unexpectedly: %v", err) + } + // Success: timeout expired without finding the worker! + } + + // 4. Add an IP + updatedPod := pod.DeepCopy() + updatedPod.Status.PodIP = "127.0.0.1" + updatedPod.Status.PodIPs = []corev1.PodIP{{IP: "127.0.0.1"}} + updatedPod.Status.Phase = corev1.PodRunning + + _, err = fakeK8s.CoreV1().Pods(ns).Update(context.Background(), updatedPod, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("failed to update pod: %v", err) + } + + // 5. Check that it's added (eventually by polling) + err = wait.PollUntilContextTimeout(context.Background(), 100*time.Millisecond, 2*time.Second, true, func(ctx context.Context) (bool, error) { + w, err := persistence.GetWorker(ctx, ns, poolName, podName) + if err != nil { + if errors.Is(err, store.ErrNotFound) { + return false, nil + } + return false, err + } + return w.Ip == "127.0.0.1", nil + }) + if err != nil { + t.Fatalf("Worker not found in Redis after update: %v", err) + } + + // 8. Delete it + err = fakeK8s.CoreV1().Pods(ns).Delete(context.Background(), podName, metav1.DeleteOptions{}) + if err != nil { + t.Fatalf("failed to delete pod: %v", err) + } + + // 9. Verify it's gone + err = wait.PollUntilContextTimeout(context.Background(), 100*time.Millisecond, 2*time.Second, true, func(ctx context.Context) (bool, error) { + _, err := persistence.GetWorker(ctx, ns, poolName, podName) + if err != nil { + if errors.Is(err, store.ErrNotFound) { + return true, nil + } + return false, err + } + return false, nil + }) + if err != nil { + t.Fatalf("Worker still found in Redis after deletion: %v", err) + } +} diff --git a/cmd/servers/ateapi/controlapi/workflow.go b/cmd/servers/ateapi/controlapi/workflow.go new file mode 100644 index 000000000..76aba665b --- /dev/null +++ b/cmd/servers/ateapi/controlapi/workflow.go @@ -0,0 +1,212 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + listersv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/google/uuid" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" + grpcCodes "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "k8s.io/apimachinery/pkg/util/wait" +) + +// WorkflowStep represents a single, idempotent operation in a workflow graph. +// Params is the immutable parameters used to start the workflow. +// Context is the mutable context fetched or modified during execution. +type WorkflowStep[Params any, Context any] interface { + // Name returns the identifier for this step (useful for logging and debugging). + Name() string + + // IsComplete checks if this step's work has already been completed. + // If it returns true, the engine skips Execute() and fast-forwards to the next step. + IsComplete(ctx context.Context, params Params, wCtx Context) (bool, error) + + // Execute performs the step's business logic and persists any state changes. + // If an error is returned, the workflow stops and relies on the client to retry. + Execute(ctx context.Context, params Params, wCtx Context) error + + // RetryBackoff returns an optional backoff configuration for this step. + // If non-nil, the workflow orchestrator automatically retries Execute() on persistence conflicts. + RetryBackoff() *wait.Backoff +} + +// RunWorkflow is a synchronous executor that iterates through a sequence of generic steps. +// It implements the Client-Driven Forward Recovery pattern. +func RunWorkflow[Params any, Context any](ctx context.Context, params Params, wCtx Context, steps []WorkflowStep[Params, Context]) error { + tracer := otel.Tracer("controlapi") + + for _, step := range steps { + if err := ctx.Err(); err != nil { + return fmt.Errorf("workflow cancelled: %w", err) + } + + ctx, span := tracer.Start(ctx, "step."+step.Name()) + + done, err := step.IsComplete(ctx, params, wCtx) + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) + span.End() + return fmt.Errorf("failed checking status of step %s: %w", step.Name(), err) + } + + if done { + span.End() + // Fast-forward past this step + continue + } + + err = runStep(ctx, params, wCtx, step) + if err != nil { + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) + span.End() + return fmt.Errorf("workflow failed at step %s: %w", step.Name(), err) + } + span.End() + } + + return nil +} + +func runStep[Params any, Context any](ctx context.Context, params Params, wCtx Context, step WorkflowStep[Params, Context]) error { + backoff := step.RetryBackoff() + if backoff == nil { + return step.Execute(ctx, params, wCtx) + } + + return wait.ExponentialBackoff(*backoff, func() (bool, error) { + if err := ctx.Err(); err != nil { + return false, err + } + execErr := step.Execute(ctx, params, wCtx) + if execErr == nil { + return true, nil + } + if errors.Is(execErr, store.ErrPersistenceRetry) { + return false, nil // retryable + } + return false, execErr // fatal + }) +} + +// ActorWorkflow handles the workflows for actor's resume / suspend operations. +type ActorWorkflow struct { + store store.Interface + dialer *AteletDialer + actorTemplateLister listersv1alpha1.ActorTemplateLister +} + +// NewActorWorkflow creates a new ActorWorkflow. +func NewActorWorkflow(store store.Interface, dialer *AteletDialer, actorTemplateLister listersv1alpha1.ActorTemplateLister) *ActorWorkflow { + return &ActorWorkflow{ + store: store, + dialer: dialer, + actorTemplateLister: actorTemplateLister, + } +} + +// ResumeActor executes the workflow to resume a suspended actor. Idempotent. +func (w *ActorWorkflow) ResumeActor(ctx context.Context, id string, boot bool) (*ateapipb.Actor, error) { + input := &ResumeInput{ + ActorID: id, + Boot: boot, + } + state := &ResumeState{} + + // Acquire lock and get the timeout context for the workflow + // Lock TTL is 7 seconds, with 2 seconds padding for workflow timeout + ctx, releaseLock, err := w.acquireActorLock(ctx, id, 30*time.Second, 2*time.Second) + if err != nil { + return nil, err + } + defer releaseLock() + + steps := []WorkflowStep[*ResumeInput, *ResumeState]{ + &LoadActorForResumeStep{store: w.store, actorTemplateLister: w.actorTemplateLister}, + &AssignWorkerStep{store: w.store}, + &CallAteletRestoreStep{dialer: w.dialer}, + &FinalizeRunningStep{store: w.store}, + } + + if err := RunWorkflow(ctx, input, state, steps); err != nil { + return nil, err + } + + return state.Actor, nil +} + +// SuspendActor executes the workflow to suspend a running actor. Idempotent. +func (w *ActorWorkflow) SuspendActor(ctx context.Context, id string) (*ateapipb.Actor, error) { + input := &SuspendInput{ + ActorID: id, + } + state := &SuspendState{} + + // Acquire lock and get the timeout context for the workflow + // Lock TTL is 7 seconds, with 2 seconds padding for workflow timeout + ctx, releaseLock, err := w.acquireActorLock(ctx, id, 30*time.Second, 2*time.Second) + if err != nil { + return nil, err + } + defer releaseLock() + + steps := []WorkflowStep[*SuspendInput, *SuspendState]{ + &LoadActorForSuspendStep{store: w.store, actorTemplateLister: w.actorTemplateLister}, + &MarkSuspendingStep{store: w.store}, + &CallAteletSuspendStep{dialer: w.dialer}, + &FinalizeSuspendedStep{store: w.store}, + } + + if err := RunWorkflow(ctx, input, state, steps); err != nil { + return nil, err + } + + return state.Actor, nil +} + +func (w *ActorWorkflow) acquireActorLock(ctx context.Context, id string, ttl time.Duration, padding time.Duration) (context.Context, func(), error) { + lockKey := "lock:actor:" + id + lockValue := uuid.New().String() + + // Create a child context for the workflow that expires BEFORE the lock + workflowTimeout := ttl - padding + workflowCtx, cancel := context.WithTimeout(ctx, workflowTimeout) + + acquired, err := w.store.AcquireLock(workflowCtx, lockKey, lockValue, ttl) + if err != nil { + cancel() + return nil, nil, fmt.Errorf("while acquiring lock: %w", err) + } + if !acquired { + cancel() + return nil, nil, status.Error(grpcCodes.Aborted, "another operation is in progress for this actor") + } + + return workflowCtx, func() { + cancel() + // Use context.Background() to ensure the lock is released even if the workflow context was canceled. + w.store.ReleaseLock(context.Background(), lockKey, lockValue) + }, nil +} diff --git a/cmd/servers/ateapi/controlapi/workflow_resume.go b/cmd/servers/ateapi/controlapi/workflow_resume.go new file mode 100644 index 000000000..744422a2c --- /dev/null +++ b/cmd/servers/ateapi/controlapi/workflow_resume.go @@ -0,0 +1,295 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "errors" + "fmt" + "log/slog" + "math/rand" + "time" + + atev1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + listersv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/agent-substrate/substrate/proto/ateletpb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "k8s.io/apimachinery/pkg/util/wait" +) + +// ResumeInput holds the immutable parameters requested by the client. +type ResumeInput struct { + ActorID string + Boot bool +} + +// ResumeState holds the mutable state loaded and modified during execution. +type ResumeState struct { + Actor *ateapipb.Actor + ActorTemplate *atev1alpha1.ActorTemplate +} + +type LoadActorForResumeStep struct { + store store.Interface + actorTemplateLister listersv1alpha1.ActorTemplateLister +} + +func (s *LoadActorForResumeStep) Name() string { return "LoadActorForResume" } +func (s *LoadActorForResumeStep) IsComplete(ctx context.Context, input *ResumeInput, state *ResumeState) (bool, error) { + // Always run this step to get the latest state from the DB + return false, nil +} +func (s *LoadActorForResumeStep) Execute(ctx context.Context, input *ResumeInput, state *ResumeState) error { + actor, err := s.store.GetActor(ctx, input.ActorID) + if err != nil { + if errors.Is(err, store.ErrNotFound) { + return status.Errorf(codes.NotFound, "Actor %s not found", input.ActorID) + } + return fmt.Errorf("while getting actor from DB: %w", err) + } + state.Actor = actor + + actorTemplate, err := s.actorTemplateLister.ActorTemplates(actor.GetActorTemplateNamespace()).Get(actor.GetActorTemplateName()) + if err != nil { + return fmt.Errorf("while getting ActorTemplate: %w", err) + } + state.ActorTemplate = actorTemplate + + return nil +} + +func (s *LoadActorForResumeStep) RetryBackoff() *wait.Backoff { return nil } + +type AssignWorkerStep struct { + store store.Interface +} + +func (s *AssignWorkerStep) Name() string { return "AssignWorker" } + +func (s *AssignWorkerStep) IsComplete(ctx context.Context, input *ResumeInput, state *ResumeState) (bool, error) { + return state.Actor.GetStatus() == ateapipb.Actor_STATUS_RUNNING, nil +} +func (s *AssignWorkerStep) Execute(ctx context.Context, input *ResumeInput, state *ResumeState) error { + workers, err := s.store.ListWorkers(ctx) + if err != nil { + return fmt.Errorf("while listing workers: %w", err) + } + + var assignedWorker *ateapipb.Worker + + // Check if we already have a worker assigned from a previous failed attempt + for _, worker := range workers { + if worker.GetActorId() == input.ActorID && worker.GetWorkerPool() == state.ActorTemplate.Spec.WorkerPoolRef.Name && worker.GetWorkerNamespace() == state.ActorTemplate.Spec.WorkerPoolRef.Namespace { + assignedWorker = worker + break + } + } + + // If not, find a free one using randomized shuffling + if assignedWorker == nil { + pickedWorker := s.findFreeWorker(workers, state.ActorTemplate.Spec.WorkerPoolRef.Namespace, state.ActorTemplate.Spec.WorkerPoolRef.Name) + if pickedWorker == nil { + return status.Errorf(codes.FailedPrecondition, "no free workers available") + } + + assignedWorker = pickedWorker + slog.InfoContext(ctx, "Picked worker", slog.Any("worker", pickedWorker.String())) + } + + assignedWorker.ActorId = input.ActorID + assignedWorker.ActorNamespace = state.Actor.GetActorTemplateNamespace() + assignedWorker.ActorTemplate = state.Actor.GetActorTemplateName() + + if err := s.store.UpdateWorker(ctx, assignedWorker, assignedWorker.Version); err != nil { + return err + } + + state.Actor.Status = ateapipb.Actor_STATUS_RESUMING + state.Actor.AteomPodNamespace = assignedWorker.GetWorkerNamespace() + state.Actor.AteomPodName = assignedWorker.GetWorkerPod() + state.Actor.AteomPodIp = assignedWorker.GetIp() + + if err := s.store.UpdateActor(ctx, state.Actor, state.Actor.GetVersion()); err != nil { + return err + } + return nil +} + +func (s *AssignWorkerStep) RetryBackoff() *wait.Backoff { + return &wait.Backoff{ + Steps: 5, + Duration: 10 * time.Millisecond, + Factor: 2.0, + Jitter: 1.0, + } +} + +func (s *AssignWorkerStep) findFreeWorker(workers []*ateapipb.Worker, workerPoolNamespace, workerPoolName string) *ateapipb.Worker { + var freeWorkers []*ateapipb.Worker + for _, worker := range workers { + if worker.GetActorId() == "" && worker.GetWorkerPool() == workerPoolName && worker.GetWorkerNamespace() == workerPoolNamespace { + freeWorkers = append(freeWorkers, worker) + } + } + + if len(freeWorkers) > 0 { + rand.Shuffle(len(freeWorkers), func(i, j int) { + freeWorkers[i], freeWorkers[j] = freeWorkers[j], freeWorkers[i] + }) + return freeWorkers[0] + } + return nil +} + +type CallAteletRestoreStep struct { + dialer *AteletDialer +} + +func (s *CallAteletRestoreStep) Name() string { return "CallAteletRestore" } +func (s *CallAteletRestoreStep) IsComplete(ctx context.Context, input *ResumeInput, state *ResumeState) (bool, error) { + return state.Actor.GetStatus() == ateapipb.Actor_STATUS_RUNNING, nil +} +func (s *CallAteletRestoreStep) Execute(ctx context.Context, input *ResumeInput, state *ResumeState) error { + ateletConn, err := s.dialer.DialForWorker(state.Actor.GetAteomPodNamespace(), state.Actor.GetAteomPodName()) + if err != nil { + return err + } + client := ateletpb.NewAteomHerderClient(ateletConn) + + workloadSpec := &ateletpb.WorkloadSpec{ + PauseImage: state.ActorTemplate.Spec.PauseImage, + } + for _, ctr := range state.ActorTemplate.Spec.Containers { + ateletCtr := &ateletpb.Container{ + Name: ctr.Name, + Image: ctr.Image, + Command: ctr.Command, + } + for _, env := range ctr.Env { + ateletEnv := &ateletpb.EnvEntry{ + Name: env.Name, + Value: env.Value, + } + ateletCtr.Env = append(ateletCtr.Env, ateletEnv) + } + workloadSpec.Containers = append(workloadSpec.Containers, ateletCtr) + } + + runscCfg := &ateletpb.RunscConfig{} + if state.ActorTemplate.Spec.Runsc.AMD64 != nil { + runscCfg.Amd64 = &ateletpb.RunscPlatformConfig{ + Sha256Hash: state.ActorTemplate.Spec.Runsc.AMD64.SHA256Hash, + Url: state.ActorTemplate.Spec.Runsc.AMD64.URL, + } + } + if state.ActorTemplate.Spec.Runsc.ARM64 != nil { + runscCfg.Arm64 = &ateletpb.RunscPlatformConfig{ + Sha256Hash: state.ActorTemplate.Spec.Runsc.ARM64.SHA256Hash, + Url: state.ActorTemplate.Spec.Runsc.ARM64.URL, + } + } + if state.ActorTemplate.Spec.Runsc.Authentication.GCP != nil { + authnCfg := &ateletpb.AuthenticationConfig{} + authnCfg.Gcp = &ateletpb.GCPAuthenticationConfig{Use: true} + runscCfg.Authentication = authnCfg + } + + if state.Actor.LastSnapshot != "" { + slog.InfoContext(ctx, "Actor has snapshot; Restoring from snapshot") + + req := &ateletpb.RestoreRequest{ + TargetAteomNamespace: state.Actor.GetAteomPodNamespace(), + TargetAteomName: state.Actor.GetAteomPodName(), + ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), + ActorTemplateName: state.Actor.GetActorTemplateName(), + ActorId: state.Actor.GetActorId(), + Runsc: runscCfg, + Spec: workloadSpec, + SnapshotUriPrefix: state.Actor.GetLastSnapshot(), + } + _, err = client.Restore(ctx, req) + if err != nil { + return fmt.Errorf("while restoring workload: %w", err) + } + return nil + } else if state.ActorTemplate.Status.GoldenSnapshot != "" && !input.Boot { + slog.InfoContext(ctx, "Actor has no snapshot; ActorTemplate has golden snapshot; Restoring from golden snapshot") + + snapshot := state.ActorTemplate.Status.GoldenSnapshot + + req := &ateletpb.RestoreRequest{ + TargetAteomNamespace: state.Actor.GetAteomPodNamespace(), + TargetAteomName: state.Actor.GetAteomPodName(), + ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), + ActorTemplateName: state.Actor.GetActorTemplateName(), + ActorId: state.Actor.GetActorId(), + Runsc: runscCfg, + Spec: workloadSpec, + SnapshotUriPrefix: snapshot, + } + _, err = client.Restore(ctx, req) + if err != nil { + return fmt.Errorf("while creating workload from golden snapshot: %w", err) + } + return nil + } else { + slog.InfoContext(ctx, "Actor has no snapshot; ActorTemplate has no golden snapshot; Booting from ActorTemplate spec") + req := &ateletpb.RunRequest{ + TargetAteomNamespace: state.Actor.GetAteomPodNamespace(), + TargetAteomName: state.Actor.GetAteomPodName(), + ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), + ActorTemplateName: state.Actor.GetActorTemplateName(), + ActorId: state.Actor.GetActorId(), + Runsc: runscCfg, + Spec: workloadSpec, + } + _, err = client.Run(ctx, req) + if err != nil { + return fmt.Errorf("while creating workload from spec: %w", err) + } + + return nil + } + // Unreachable +} + +func (s *CallAteletRestoreStep) RetryBackoff() *wait.Backoff { return nil } + +type FinalizeRunningStep struct { + store store.Interface +} + +func (s *FinalizeRunningStep) Name() string { return "FinalizeRunning" } +func (s *FinalizeRunningStep) IsComplete(ctx context.Context, input *ResumeInput, state *ResumeState) (bool, error) { + return state.Actor.GetStatus() == ateapipb.Actor_STATUS_RUNNING, nil +} +func (s *FinalizeRunningStep) Execute(ctx context.Context, input *ResumeInput, state *ResumeState) error { + latestActor, err := s.store.GetActor(ctx, input.ActorID) + if err != nil { + return err + } + + latestActor.Status = ateapipb.Actor_STATUS_RUNNING + err = s.store.UpdateActor(ctx, latestActor, latestActor.GetVersion()) + if err == nil { + state.Actor = latestActor + } + return err +} + +func (s *FinalizeRunningStep) RetryBackoff() *wait.Backoff { return nil } diff --git a/cmd/servers/ateapi/controlapi/workflow_suspend.go b/cmd/servers/ateapi/controlapi/workflow_suspend.go new file mode 100644 index 000000000..458f0f50d --- /dev/null +++ b/cmd/servers/ateapi/controlapi/workflow_suspend.go @@ -0,0 +1,240 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controlapi + +import ( + "context" + "crypto/rand" + "errors" + "fmt" + "log/slog" + "strings" + "time" + + atev1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + listersv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/agent-substrate/substrate/proto/ateletpb" + "k8s.io/apimachinery/pkg/util/wait" +) + +// SuspendInput holds the immutable parameters requested by the client. +type SuspendInput struct { + ActorID string +} + +// SuspendState holds the mutable state loaded and modified during execution. +type SuspendState struct { + Actor *ateapipb.Actor + ActorTemplate *atev1alpha1.ActorTemplate +} + +type LoadActorForSuspendStep struct { + store store.Interface + actorTemplateLister listersv1alpha1.ActorTemplateLister +} + +func (s *LoadActorForSuspendStep) Name() string { return "LoadActorForSuspend" } +func (s *LoadActorForSuspendStep) IsComplete(ctx context.Context, input *SuspendInput, state *SuspendState) (bool, error) { + // Always run to get the freshest state + return false, nil +} +func (s *LoadActorForSuspendStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { + actor, err := s.store.GetActor(ctx, input.ActorID) + if err != nil { + return err + } + state.Actor = actor + + actorTemplate, err := s.actorTemplateLister.ActorTemplates(actor.GetActorTemplateNamespace()).Get(actor.GetActorTemplateName()) + if err != nil { + return fmt.Errorf("while getting ActorTemplate: %w", err) + } + state.ActorTemplate = actorTemplate + + return nil +} + +func (s *LoadActorForSuspendStep) RetryBackoff() *wait.Backoff { return nil } + +type MarkSuspendingStep struct { + store store.Interface +} + +func (s *MarkSuspendingStep) Name() string { return "MarkSuspending" } +func (s *MarkSuspendingStep) IsComplete(ctx context.Context, input *SuspendInput, state *SuspendState) (bool, error) { + // Fast forward if we've already marked our intent or if we are further along. + return state.Actor.GetStatus() == ateapipb.Actor_STATUS_SUSPENDING || state.Actor.GetStatus() == ateapipb.Actor_STATUS_SUSPENDED, nil +} +func (s *MarkSuspendingStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { + if state.Actor.GetStatus() != ateapipb.Actor_STATUS_RUNNING { + return nil + } + + state.Actor.Status = ateapipb.Actor_STATUS_SUSPENDING + snapshotID := time.Now().Format(time.RFC3339) + "-" + rand.Text() + state.Actor.InProgressSnapshot = strings.TrimSuffix(state.ActorTemplate.Spec.SnapshotsConfig.Location, "/") + "/" + input.ActorID + "/" + snapshotID + return s.store.UpdateActor(ctx, state.Actor, state.Actor.GetVersion()) +} + +func (s *MarkSuspendingStep) RetryBackoff() *wait.Backoff { return nil } + +type CallAteletSuspendStep struct { + dialer *AteletDialer +} + +func (s *CallAteletSuspendStep) Name() string { return "CallAteletSuspend" } +func (s *CallAteletSuspendStep) IsComplete(ctx context.Context, input *SuspendInput, state *SuspendState) (bool, error) { + // If we are already SUSPENDED, we've already called Atelet + return state.Actor.GetStatus() == ateapipb.Actor_STATUS_SUSPENDED, nil +} +func (s *CallAteletSuspendStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { + if state.Actor.GetAteomPodNamespace() == "" { + return fmt.Errorf("actor is in SUSPENDING state but has no active worker") + } + + ateletConn, err := s.dialer.DialForWorker(state.Actor.GetAteomPodNamespace(), state.Actor.GetAteomPodName()) + if err != nil { + if errors.Is(err, ErrWorkerPodNotFound) { + slog.Warn("Skipping suspend for dangling worker pod", "namespace", state.Actor.GetAteomPodNamespace(), "pod", state.Actor.GetAteomPodName()) + return nil + } + return fmt.Errorf("while getting atelet conn for worker pod: %w", err) + } + client := ateletpb.NewAteomHerderClient(ateletConn) + + runscCfg := &ateletpb.RunscConfig{} + if state.ActorTemplate.Spec.Runsc.AMD64 != nil { + runscCfg.Amd64 = &ateletpb.RunscPlatformConfig{ + Sha256Hash: state.ActorTemplate.Spec.Runsc.AMD64.SHA256Hash, + Url: state.ActorTemplate.Spec.Runsc.AMD64.URL, + } + } + if state.ActorTemplate.Spec.Runsc.ARM64 != nil { + runscCfg.Arm64 = &ateletpb.RunscPlatformConfig{ + Sha256Hash: state.ActorTemplate.Spec.Runsc.ARM64.SHA256Hash, + Url: state.ActorTemplate.Spec.Runsc.ARM64.URL, + } + } + if state.ActorTemplate.Spec.Runsc.Authentication.GCP != nil { + authnCfg := &ateletpb.AuthenticationConfig{} + authnCfg.Gcp = &ateletpb.GCPAuthenticationConfig{Use: true} + runscCfg.Authentication = authnCfg + } + + req := &ateletpb.CheckpointRequest{ + TargetAteomNamespace: state.Actor.GetAteomPodNamespace(), + TargetAteomName: state.Actor.GetAteomPodName(), + ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), + ActorTemplateName: state.Actor.GetActorTemplateName(), + ActorId: state.Actor.GetActorId(), + Runsc: runscCfg, + Spec: &ateletpb.WorkloadSpec{ + PauseImage: state.ActorTemplate.Spec.PauseImage, + }, + SnapshotUriPrefix: state.Actor.GetInProgressSnapshot(), + } + for _, ctr := range state.ActorTemplate.Spec.Containers { + ateletCtr := &ateletpb.Container{ + Name: ctr.Name, + Image: ctr.Image, + Command: ctr.Command, + } + for _, env := range ctr.Env { + ateletEnv := &ateletpb.EnvEntry{ + Name: env.Name, + Value: env.Value, + } + ateletCtr.Env = append(ateletCtr.Env, ateletEnv) + } + req.Spec.Containers = append(req.Spec.Containers, ateletCtr) + } + _, err = client.Checkpoint(ctx, req) + if err != nil { + return fmt.Errorf("while checkpointing workload: %w", err) + } + + return nil +} + +func (s *CallAteletSuspendStep) RetryBackoff() *wait.Backoff { return nil } + +type FinalizeSuspendedStep struct { + store store.Interface +} + +func (s *FinalizeSuspendedStep) Name() string { return "FinalizeSuspended" } +func (s *FinalizeSuspendedStep) IsComplete(ctx context.Context, input *SuspendInput, state *SuspendState) (bool, error) { + // The workflow is completely done ONLY if the status is SUSPENDED *and* we've successfully freed the worker. + return state.Actor.GetStatus() == ateapipb.Actor_STATUS_SUSPENDED && state.Actor.GetAteomPodNamespace() == "", nil +} +func (s *FinalizeSuspendedStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { + latestActor, err := s.store.GetActor(ctx, input.ActorID) + if err != nil { + return err + } + + // 1. Free the worker (if it hasn't been freed yet) + if latestActor.GetAteomPodNamespace() != "" { + workerNs := latestActor.GetAteomPodNamespace() + workerPod := latestActor.GetAteomPodName() + + workerPool := state.ActorTemplate.Spec.WorkerPoolRef.Name + + worker, err := s.store.GetWorker(ctx, workerNs, workerPool, workerPod) + if err != nil { + if !errors.Is(err, store.ErrNotFound) { + return fmt.Errorf("while getting worker for release: %w", err) + } + slog.Warn("Worker already gone during finalize suspend, skipping release", "worker", workerPod) + } else { + // Only free it if it still belongs to us + if worker.GetActorId() == input.ActorID { + worker.ActorNamespace = "" + worker.ActorTemplate = "" + worker.ActorId = "" + + err = s.store.UpdateWorker(ctx, worker, worker.Version) + if err != nil { + return err + } + } + } + + // 2. Safely clear ActiveWorker now that the worker object in DB is freed + latestActor, err = s.store.GetActor(ctx, input.ActorID) + if err != nil { + return err + } + latestActor.Status = ateapipb.Actor_STATUS_SUSPENDED + if latestActor.InProgressSnapshot != "" { + latestActor.LastSnapshot = latestActor.InProgressSnapshot + latestActor.InProgressSnapshot = "" + } + latestActor.AteomPodNamespace = "" + latestActor.AteomPodName = "" + latestActor.AteomPodIp = "" + err = s.store.UpdateActor(ctx, latestActor, latestActor.GetVersion()) + if err != nil { + return err + } + } + + state.Actor = latestActor + return nil +} + +func (s *FinalizeSuspendedStep) RetryBackoff() *wait.Backoff { return nil } diff --git a/cmd/servers/ateapi/sessionidentity/sessionidentity.go b/cmd/servers/ateapi/sessionidentity/sessionidentity.go new file mode 100644 index 000000000..55f365426 --- /dev/null +++ b/cmd/servers/ateapi/sessionidentity/sessionidentity.go @@ -0,0 +1,222 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sessionidentity + +import ( + "context" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "fmt" + "log/slog" + "net/url" + "os" + "path" + "strings" + "time" + + "github.com/agent-substrate/substrate/internal/k8sjwt" + "github.com/agent-substrate/substrate/internal/localca" + "github.com/agent-substrate/substrate/internal/localjwtauthority" + "github.com/agent-substrate/substrate/internal/sessionidjwt" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" + "google.golang.org/grpc/status" +) + +// Server implements ateapipb.SessionIdentityServer +type Server struct { + ateapipb.UnimplementedSessionIdentityServer + + clientJWTIssuer string + clientJWTAudience string + + // TODO: Cache the signing keys in memory, so we don't read from a file every time. + sessionIDJWTPoolFile string + sessionIDCAPoolFile string + + workerCACerts string +} + +var _ ateapipb.SessionIdentityServer = (*Server)(nil) + +func New(clientJWTIssuer, clientJWTAudience, sessionIDJWTPoolFile, sessionIDCAPoolFile, workerCACerts string) *Server { + return &Server{ + clientJWTIssuer: clientJWTIssuer, + clientJWTAudience: clientJWTAudience, + sessionIDJWTPoolFile: sessionIDJWTPoolFile, + sessionIDCAPoolFile: sessionIDCAPoolFile, + workerCACerts: workerCACerts, + } +} + +func (s *Server) MintJWT(ctx context.Context, req *ateapipb.MintJWTRequest) (*ateapipb.MintJWTResponse, error) { + reqMetadata, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, fmt.Errorf("no metadata found") + } + + authorization := reqMetadata["authorization"] + if len(authorization) != 1 { + return nil, status.Errorf(codes.Unauthenticated, "Need authorization header") + } + + clientJWT := strings.TrimPrefix(authorization[0], "Bearer ") + + clientClaims, err := k8sjwt.Verify(ctx, clientJWT, s.clientJWTIssuer, s.clientJWTAudience, time.Now()) + if err != nil { + slog.ErrorContext(ctx, "Error while verifying client JWT", slog.Any("err", err)) + return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated") + } + + slog.InfoContext(ctx, "Verified client JWT", slog.Any("claims", clientClaims)) + + // TODO: Extract K8s identity from incoming JWT + + // TODO: Cross-check requested session and user claims against the session database. + + // TODO: Cache signing keys in memory, so we don't read from disk every time. + signingPoolBytes, err := os.ReadFile(s.sessionIDJWTPoolFile) + if err != nil { + return nil, fmt.Errorf("while reading signing pool bytes: %w", err) + } + + signingPool, err := localjwtauthority.Unmarshal(signingPoolBytes) + if err != nil { + return nil, fmt.Errorf("while unmarshaling signing pool: %w", err) + } + + // We only issue tokens with audience bindings. + if len(req.GetAudience()) == 0 { + return nil, fmt.Errorf("at least one audience must be requested") + } + + sessionClaims := &sessionidjwt.Claims{ + Issuer: "https://broker.agentic-substrate-session-id-broker.svc", // TODO: This needs to be globally unique. + Subject: fmt.Sprintf("apps/%s/users/%s/sessions/%s", req.GetAppId(), req.GetUserId(), req.GetSessionId()), + Audiences: req.GetAudience(), + Expiration: time.Now().Add(15 * time.Minute), + NotBefore: time.Now().Add(-5 * time.Minute), + IssuedAt: time.Now(), + JTI: rand.Text(), + + Substrate: sessionidjwt.SubstrateClaims{ + AppID: req.GetAppId(), + UserID: req.GetUserId(), + SessionID: req.GetSessionId(), + }, + } + + sessionWireClaims, err := sessionidjwt.ClaimsToWire(sessionClaims) + if err != nil { + return nil, fmt.Errorf("while making session JWT claims: %w", err) + } + + // Assume the first authority is the one to use for signing. + sessionJWT, err := sessionidjwt.Sign(sessionWireClaims, signingPool.Authorities[0].SigningKey, signingPool.Authorities[0].Algorithm, signingPool.Authorities[0].ID) + if err != nil { + return nil, fmt.Errorf("while signing session JWT: %w", err) + } + + return &ateapipb.MintJWTResponse{ + SessionJwt: sessionJWT, + }, nil +} + +func (s *Server) MintCert(ctx context.Context, req *ateapipb.MintCertRequest) (*ateapipb.MintCertResponse, error) { + p, ok := peer.FromContext(ctx) + if !ok { + return nil, status.Errorf(codes.Unauthenticated, "no peer transport information found") + } + + tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo) + if !ok { + return nil, status.Errorf(codes.Unauthenticated, "unexpected peer transport credentials") + } + + if len(tlsInfo.State.PeerCertificates) == 0 { + return nil, status.Errorf(codes.Unauthenticated, "could not verify peer certificate") + } + + // TODO: How to verify pod cert <-> session mapping? + appID := req.GetAppId() + userID := req.GetUserId() + sessionID := req.GetSessionId() + + if appID == "" || userID == "" || sessionID == "" { + return nil, status.Errorf(codes.InvalidArgument, "app_id, user_id, and session_id are required") + } + + // Load the CA pool for signing + poolBytes, err := os.ReadFile(s.sessionIDCAPoolFile) + if err != nil { + slog.ErrorContext(ctx, "Failed to read session CA pool file", slog.Any("err", err)) + return nil, status.Errorf(codes.Internal, "Failed to load session CA") + } + caPool, err := localca.Unmarshal(poolBytes) + if err != nil || len(caPool.CAs) == 0 { + slog.ErrorContext(ctx, "Failed to load session CA", slog.Any("err", err)) + return nil, status.Errorf(codes.Internal, "Failed to load session CA") + } + + // Parse the CSR + csr, err := x509.ParseCertificateRequest(req.GetCertificateSigningRequest()) + if err != nil { + slog.ErrorContext(ctx, "Failed to parse CSR", slog.Any("err", err)) + return nil, status.Errorf(codes.Internal, "Failed to parse CSR") + } + if err := csr.CheckSignature(); err != nil { + slog.ErrorContext(ctx, "Failed to verify CSR signature", slog.Any("err", err)) + return nil, status.Errorf(codes.Internal, "Failed to verify CSR signature") + } + + spiffeURI := &url.URL{ + Scheme: "spiffe", + Host: "substrate-session.local", + Path: path.Join("app", appID, "user", userID, "session", sessionID), + } + template := &x509.Certificate{ + URIs: []*url.URL{spiffeURI}, + NotBefore: time.Now().Add(-5 * time.Minute), + NotAfter: time.Now().Add(15 * time.Minute), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + IsCA: false, + Issuer: pkix.Name{ + CommonName: "api.ate-system.svc.cluster.local", + }, + } + + // Sign and return the session cert. + ca := caPool.CAs[0] + derBytes, err := x509.CreateCertificate(rand.Reader, template, ca.RootCertificate, csr.PublicKey, ca.SigningKey) + if err != nil { + slog.ErrorContext(ctx, "Failed to sign certificate", slog.Any("err", err)) + return nil, status.Errorf(codes.Internal, "Failed to sign certificate") + } + + certificates := [][]byte{derBytes} + for _, intermed := range ca.IntermediateCertificates { + certificates = append(certificates, intermed.Raw) + } + + return &ateapipb.MintCertResponse{ + SessionCertificates: certificates, + }, nil +} diff --git a/cmd/servers/ateapi/store/ateredis/ateredis.go b/cmd/servers/ateapi/store/ateredis/ateredis.go new file mode 100644 index 000000000..ebde32240 --- /dev/null +++ b/cmd/servers/ateapi/store/ateredis/ateredis.go @@ -0,0 +1,454 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package ateredis is an ate storage backend built on Redis. +// +// Actors are stored in keys of the form +// `actor:`. They are +// stored as DBActor JSON-serialized objects, which lets us manipulate them from +// Redis lua. +// +// Workers are stored in keys of the form +// `worker:::`, holding a DBWorker JSON object. +// +// Note that redis lua scripting has a restriction that informed the data design +// here -- a lua script must predeclare all keys it is going to access. It +// cannot read one key, then derive another key from the value, and read it. +// This is why we store the worker status inline in the Actor. +// +// Additionally, redis / valkey in cluster mode have a serious restriction that +// informs our data model: it is not possible for a single "action" to touch +// keys that hash to to different cluster slots. This includes lua scripts. The +// biggest implication here is that it is not possible to atomically mark an +// actor as scheduled on a worker, and the worker as busy. So we need to be +// very careful about the order in which we take these actions. +// +// Note also (but I cannot find documentation one way or another) that Redis Lua +// is not ACID --- power failure, etc may leave us with half of the effects of a +// script applied. +package ateredis + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + "time" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/redis/go-redis/v9" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +type redisClient interface { + redis.Cmdable + ForEachMaster(ctx context.Context, fn func(ctx context.Context, client *redis.Client) error) error + Watch(ctx context.Context, fn func(*redis.Tx) error, keys ...string) error +} + +// Persistence is a service that stores information about applications in Redis. +type Persistence struct { + rdb redisClient +} + +var _ store.Interface = (*Persistence)(nil) + +// NewPersistence creates a new Persistence. +func NewPersistence(redisClient *redis.ClusterClient) *Persistence { + return &Persistence{ + rdb: redisClient, + } +} + +func actorDBKey(id string) string { + return "actor:" + id +} + +func workerDBKey(namespace, poolName, podName string) string { + return "worker:" + namespace + ":" + poolName + ":" + podName +} + +// DebugClearAll flushes all data from Redis. +func (s *Persistence) DebugClearAll(ctx context.Context) error { + // Iterate through every Primary (Master) node in the cluster + err := s.rdb.ForEachMaster(ctx, func(ctx context.Context, master *redis.Client) error { + // Log which shard we are currently flushing (optional but helpful for debugging) + shardAddr := master.Options().Addr + fmt.Printf("Flushing shard: %s\n", shardAddr) + + // Execute the flush on this specific shard + return master.FlushAllAsync(ctx).Err() + }) + return err +} + +func (s *Persistence) GetActor(ctx context.Context, id string) (*ateapipb.Actor, error) { + dbKey := actorDBKey(id) + + dbActorBytes, err := s.rdb.Get(ctx, dbKey).Bytes() + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, store.ErrNotFound + } + return nil, fmt.Errorf("while getting actor key %q: %w", dbKey, err) + } + + actor := &ateapipb.Actor{} + if err := protojson.Unmarshal(dbActorBytes, actor); err != nil { + return nil, fmt.Errorf("while unmarshaling actor: %w", err) + } + + if actor.GetActorId() != id { + return nil, fmt.Errorf("(impossible) mismatch between stored id and key id") + } + + return actor, nil +} + +func (s *Persistence) CreateActor(ctx context.Context, actor *ateapipb.Actor) error { + dbKey := actorDBKey(actor.GetActorId()) + + // Clone because we will update the version field, and we don't want to + // stomp the caller's copy. + dbActor := proto.Clone(actor).(*ateapipb.Actor) + dbActor.Version = 1 + + dbActorBytes, err := protojson.Marshal(dbActor) + if err != nil { + return fmt.Errorf("in protojson.Marshal: %w", err) + } + + ok, err := s.rdb.SetNX(ctx, dbKey, dbActorBytes, 0).Result() + if err != nil { + return fmt.Errorf("while executing redis set: %w", err) + } + if !ok { + return store.ErrAlreadyExists + } + + return nil +} + +func (s *Persistence) CreateWorker(ctx context.Context, worker *ateapipb.Worker) error { + dbKey := workerDBKey(worker.GetWorkerNamespace(), worker.GetWorkerPool(), worker.GetWorkerPod()) + + // Clone because we will update the version field, and we don't want to + // stomp the caller's copy. + dbWorker := proto.Clone(worker).(*ateapipb.Worker) + dbWorker.Version = 1 + + dbWorkerBytes, err := protojson.Marshal(dbWorker) + if err != nil { + return fmt.Errorf("in protojson.Marshal: %w", err) + } + + ok, err := s.rdb.SetNX(ctx, dbKey, dbWorkerBytes, 0).Result() + if err != nil { + return fmt.Errorf("while executing redis set: %w", err) + } + if !ok { + return store.ErrAlreadyExists + } + + return nil +} + +func (s *Persistence) GetWorker(ctx context.Context, namespace, pool, pod string) (*ateapipb.Worker, error) { + dbKey := workerDBKey(namespace, pool, pod) + + dbWorkerBytes, err := s.rdb.Get(ctx, dbKey).Bytes() + if err != nil { + if errors.Is(err, redis.Nil) { + return nil, store.ErrNotFound + } + return nil, fmt.Errorf("while getting worker key %q: %w", dbKey, err) + } + + worker := &ateapipb.Worker{} + if err := protojson.Unmarshal(dbWorkerBytes, worker); err != nil { + return nil, fmt.Errorf("in protojson.Unmarshal: %w", err) + } + + if worker.GetWorkerNamespace() != namespace || worker.GetWorkerPool() != pool || worker.GetWorkerPod() != pod { + return nil, fmt.Errorf("(impossible) mismatch between stored namespace/pool/pod and key") + } + + return worker, nil +} + +func (s *Persistence) UpdateWorker(ctx context.Context, worker *ateapipb.Worker, expectedVersion int64) error { + dbKey := workerDBKey(worker.GetWorkerNamespace(), worker.GetWorkerPool(), worker.GetWorkerPod()) + + // Clone because we will update the version field, and we don't want to + // stomp the caller's copy. + dbWorker := proto.Clone(worker).(*ateapipb.Worker) + + err := s.rdb.Watch(ctx, func(tx *redis.Tx) error { + currentVal, err := tx.Get(ctx, dbKey).Bytes() + if err != nil { + if errors.Is(err, redis.Nil) { + return fmt.Errorf("worker does not exist") + } + return fmt.Errorf("while getting worker: %w", err) + } + + currentWorker := &ateapipb.Worker{} + if err := protojson.Unmarshal(currentVal, currentWorker); err != nil { + return fmt.Errorf("in protojson.Unmarshal: %w", err) + } + + if currentWorker.GetVersion() != expectedVersion { + return store.ErrPersistenceRetry + } + dbWorker.Version = currentWorker.GetVersion() + 1 + if currentWorker.GetWorkerNamespace() != dbWorker.GetWorkerNamespace() { + return fmt.Errorf("worker_namespace is immutable") + } + if currentWorker.GetWorkerPool() != dbWorker.GetWorkerPool() { + return fmt.Errorf("worker_pool is immutable") + } + if currentWorker.GetWorkerPod() != dbWorker.GetWorkerPod() { + return fmt.Errorf("worker_pod is immutable") + } + if currentWorker.GetIp() != dbWorker.GetIp() { + return fmt.Errorf("ip is immutable") + } + + newVal, err := protojson.Marshal(dbWorker) + if err != nil { + return fmt.Errorf("in protojson.Marshal: %w", err) + } + + _, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error { + pipe.Set(ctx, dbKey, newVal, 0) + return nil + }) + return err + }, dbKey) + if err != nil { + if errors.Is(err, store.ErrPersistenceRetry) || errors.Is(err, redis.TxFailedErr) { + return store.ErrPersistenceRetry + } + return fmt.Errorf("while executing update worker transaction: %w", err) + } + + return nil +} + +func (s *Persistence) DeleteWorker(ctx context.Context, namespace, pool, pod string) error { + dbKey := workerDBKey(namespace, pool, pod) + err := s.rdb.Del(ctx, dbKey).Err() + if err != nil { + return fmt.Errorf("while deleting worker key %q: %w", dbKey, err) + } + return nil +} + +func (s *Persistence) DeleteActor(ctx context.Context, id string) error { + dbKey := actorDBKey(id) + err := s.rdb.Watch(ctx, func(tx *redis.Tx) error { + currentVal, err := tx.Get(ctx, dbKey).Bytes() + if err != nil { + if errors.Is(err, redis.Nil) { + return store.ErrNotFound + } + return fmt.Errorf("while getting actor: %w", err) + } + + currentActor := &ateapipb.Actor{} + if err := protojson.Unmarshal(currentVal, currentActor); err != nil { + return fmt.Errorf("in protojson.Unmarshal: %w", err) + } + + if currentActor.GetStatus() != ateapipb.Actor_STATUS_SUSPENDED { + return store.ErrFailedPrecondition + } + + _, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error { + pipe.Del(ctx, dbKey) + return nil + }) + return err + }, dbKey) + + if err != nil { + if errors.Is(err, redis.TxFailedErr) { + return store.ErrPersistenceRetry + } + return err + } + + return nil +} + +func (s *Persistence) UpdateActor(ctx context.Context, actor *ateapipb.Actor, expectedVersion int64) error { + dbKey := actorDBKey(actor.GetActorId()) + + // Clone because we will update the version field, and we don't want to + // stomp the caller's copy. + dbActor := proto.Clone(actor).(*ateapipb.Actor) + + err := s.rdb.Watch(ctx, func(tx *redis.Tx) error { + currentVal, err := tx.Get(ctx, dbKey).Bytes() + if err != nil { + if errors.Is(err, redis.Nil) { + return fmt.Errorf("actor does not exist") + } + return fmt.Errorf("while getting actor: %w", err) + } + + currentActor := &ateapipb.Actor{} + if err := protojson.Unmarshal(currentVal, currentActor); err != nil { + return fmt.Errorf("in protojson.Unmarshal: %w", err) + } + + if currentActor.GetVersion() != expectedVersion { + return store.ErrPersistenceRetry + } + dbActor.Version = currentActor.GetVersion() + 1 + if currentActor.GetActorId() != dbActor.GetActorId() { + return fmt.Errorf("actor_id is immutable") + } + if currentActor.GetActorTemplateNamespace() != dbActor.GetActorTemplateNamespace() { + return fmt.Errorf("actor_template_namespace is immutable") + } + if currentActor.GetActorTemplateName() != dbActor.GetActorTemplateName() { + return fmt.Errorf("actor_template_name is immutable") + } + + newVal, err := protojson.Marshal(dbActor) + if err != nil { + return fmt.Errorf("in protojson.Marshal: %w", err) + } + + _, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error { + pipe.Set(ctx, dbKey, newVal, 0) + return nil + }) + return err + }, dbKey) + + if err != nil { + if errors.Is(err, store.ErrPersistenceRetry) || errors.Is(err, redis.TxFailedErr) { + return store.ErrPersistenceRetry + } + return fmt.Errorf("while executing update actor transaction: %w", err) + } + + actor.Version = dbActor.Version + return nil +} + +func (s *Persistence) ListWorkers(ctx context.Context) ([]*ateapipb.Worker, error) { + var result []*ateapipb.Worker + var mu sync.Mutex + + // Iterate through every Primary (Master) node in the cluster + err := s.rdb.ForEachMaster(ctx, func(ctx context.Context, master *redis.Client) error { + iter := master.Scan(ctx, 0, "worker:*", 0).Iterator() + for iter.Next(ctx) { + workerKey := iter.Val() + parts := strings.Split(workerKey, ":") + if len(parts) != 4 { + return fmt.Errorf("bad key format %q", workerKey) + } + + getCmd := master.Get(ctx, workerKey) + if getCmd.Err() != nil { + return fmt.Errorf("while getting worker %q: %w", workerKey, getCmd.Err()) + } + + worker := &ateapipb.Worker{} + if err := protojson.Unmarshal([]byte(getCmd.Val()), worker); err != nil { + return fmt.Errorf("in protojson.Unmarshal: %w", err) + } + + mu.Lock() + result = append(result, worker) + mu.Unlock() + } + if err := iter.Err(); err != nil { + return fmt.Errorf("error from iterator: %w", err) + } + + return nil + }) + if err != nil { + return nil, fmt.Errorf("while iterating all redis master: %w", err) + } + return result, nil +} + +func (s *Persistence) ListActors(ctx context.Context) ([]*ateapipb.Actor, error) { + var result []*ateapipb.Actor + var mu sync.Mutex + + err := s.rdb.ForEachMaster(ctx, func(ctx context.Context, master *redis.Client) error { + iter := master.Scan(ctx, 0, "actor:*", 0).Iterator() + for iter.Next(ctx) { + actorKey := iter.Val() + parts := strings.Split(actorKey, ":") + if len(parts) != 2 { + return fmt.Errorf("bad key format %q", actorKey) + } + + getCmd := master.Get(ctx, actorKey) + if getCmd.Err() != nil { + return fmt.Errorf("while getting actor %q: %w", actorKey, getCmd.Err()) + } + + actor := &ateapipb.Actor{} + if err := protojson.Unmarshal([]byte(getCmd.Val()), actor); err != nil { + return fmt.Errorf("in protojson.Unmarshal: %w", err) + } + + mu.Lock() + result = append(result, actor) + mu.Unlock() + } + return iter.Err() + }) + + if err != nil { + return nil, fmt.Errorf("while iterating all redis master: %w", err) + } + return result, nil +} + +func (s *Persistence) AcquireLock(ctx context.Context, key string, value string, ttl time.Duration) (bool, error) { + ok, err := s.rdb.SetNX(ctx, key, value, ttl).Result() + if err != nil { + return false, fmt.Errorf("while acquiring lock for %q: %w", key, err) + } + return ok, nil +} + +func (s *Persistence) ReleaseLock(ctx context.Context, key string, value string) error { + var luaRelease = redis.NewScript(` + if redis.call("get", KEYS[1]) == ARGV[1] then + return redis.call("del", KEYS[1]) + else + return 0 + end + `) + + _, err := luaRelease.Run(ctx, s.rdb, []string{key}, value).Result() + if err != nil { + return fmt.Errorf("while releasing lock for %q with value %q: %w", key, value, err) + } + return nil +} diff --git a/cmd/servers/ateapi/store/ateredis/ateredis_test.go b/cmd/servers/ateapi/store/ateredis/ateredis_test.go new file mode 100644 index 000000000..acc0fdaac --- /dev/null +++ b/cmd/servers/ateapi/store/ateredis/ateredis_test.go @@ -0,0 +1,723 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ateredis + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/alicebob/miniredis/v2" + "github.com/google/go-cmp/cmp" + "github.com/redis/go-redis/v9" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +func setupTest(t *testing.T) (*miniredis.Miniredis, *Persistence, context.Context) { + mr, err := miniredis.Run() + if err != nil { + t.Fatalf("failed to start miniredis: %v", err) + } + // Miniredis runs as a single node, but ClusterClient can work with it + // if we don't use cluster-specific commands that miniredis doesn't support. + // Miniredis supports most standard commands. + rdb := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{mr.Addr()}, + }) + return mr, &Persistence{rdb: rdb}, context.Background() +} + +func TestGetActor_NotFound(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + _, err := s.GetActor(ctx, "non-existent") + if !errors.Is(err, store.ErrNotFound) { + t.Errorf("expected ErrNotFound, got %v", err) + } +} + +func TestCreateActor_Success(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor := &ateapipb.Actor{ + ActorId: "session-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "test-template", + Status: ateapipb.Actor_STATUS_SUSPENDED, + } + + err := s.CreateActor(ctx, actor) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + got, err := s.GetActor(ctx, actor.ActorId) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + + expected := proto.Clone(actor).(*ateapipb.Actor) + expected.Version = 1 + + if diff := cmp.Diff(expected, got, protocmp.Transform()); diff != "" { + t.Errorf("GetActor returned unexpected actor (-want +got):\n%s", diff) + } +} + +func TestCreateActor_AlreadyExists(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor := &ateapipb.Actor{ + ActorId: "session-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "test-template", + Status: ateapipb.Actor_STATUS_SUSPENDED, + } + + err := s.CreateActor(ctx, actor) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + err = s.CreateActor(ctx, actor) + if err == nil { + t.Errorf("expected error creating existing actor, got nil") + } +} + +func TestUpdateActor_Success(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor := &ateapipb.Actor{ + ActorId: "session-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "test-template", + Status: ateapipb.Actor_STATUS_SUSPENDED, + } + + err := s.CreateActor(ctx, actor) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + actor.Status = ateapipb.Actor_STATUS_RUNNING + actor.Version = 1 + + err = s.UpdateActor(ctx, actor, 1) + if err != nil { + t.Fatalf("UpdateActor failed: %v", err) + } + + if actor.Version != 2 { + t.Errorf("expected actor.Version to be updated to 2, got %d", actor.Version) + } + + updated, err := s.GetActor(ctx, actor.ActorId) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + + expected := proto.Clone(actor).(*ateapipb.Actor) + + if diff := cmp.Diff(expected, updated, protocmp.Transform()); diff != "" { + t.Errorf("UpdateActor yielded unexpected state in DB (-want +got):\n%s", diff) + } +} + +func TestUpdateActor_Conflict(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor := &ateapipb.Actor{ + ActorId: "session-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "test-template", + Status: ateapipb.Actor_STATUS_SUSPENDED, + } + + err := s.CreateActor(ctx, actor) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + // Fetch instance 1 + actor1, err := s.GetActor(ctx, actor.ActorId) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + + // Fetch instance 2 (stale after actor1 updates) + actor2, err := s.GetActor(ctx, actor.ActorId) + if err != nil { + t.Fatalf("GetActor failed: %v", err) + } + + // Update instance 1 + actor1.Status = ateapipb.Actor_STATUS_RUNNING + err = s.UpdateActor(ctx, actor1, actor1.GetVersion()) + if err != nil { + t.Fatalf("UpdateActor failed: %v", err) + } + + // Try to update instance 2 (which has stale version) + actor2.Status = ateapipb.Actor_STATUS_SUSPENDED + err = s.UpdateActor(ctx, actor2, actor2.GetVersion()) + if !errors.Is(err, store.ErrPersistenceRetry) { + t.Errorf("expected ErrPersistenceRetry, got %v", err) + } +} + +func TestGetWorker_NotFound(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + _, err := s.GetWorker(ctx, "default", "pool-1", "non-existent") + if !errors.Is(err, store.ErrNotFound) { + t.Errorf("expected ErrNotFound, got %v", err) + } +} + +func TestCreateWorker_Success(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + worker := &ateapipb.Worker{ + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + } + + err := s.CreateWorker(ctx, worker) + if err != nil { + t.Fatalf("CreateWorker failed: %v", err) + } + + got, err := s.GetWorker(ctx, "default", "pool-1", "pod-1") + if err != nil { + t.Fatalf("GetWorker failed: %v", err) + } + + if got.Version != 1 { + t.Errorf("expected version 1, got %d", got.Version) + } + + worker.Version = 1 + if diff := cmp.Diff(worker, got, protocmp.Transform()); diff != "" { + t.Errorf("GetWorker returned unexpected worker (-want +got):\n%s", diff) + } +} + +func TestUpdateWorker_Success(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + worker := &ateapipb.Worker{ + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + } + + err := s.CreateWorker(ctx, worker) + if err != nil { + t.Fatalf("CreateWorker failed: %v", err) + } + + worker.ActorNamespace = "default" + worker.ActorTemplate = "test-template" + worker.ActorId = "session-1" + + err = s.UpdateWorker(ctx, worker, 1) + if err != nil { + t.Fatalf("UpdateWorker failed: %v", err) + } + + got, err := s.GetWorker(ctx, "default", "pool-1", "pod-1") + if err != nil { + t.Fatalf("GetWorker failed: %v", err) + } + + if got.Version != 2 { + t.Errorf("expected version 2, got %d", got.Version) + } + + worker.Version = 2 + if diff := cmp.Diff(worker, got, protocmp.Transform()); diff != "" { + t.Errorf("UpdateWorker yielded unexpected state in DB (-want +got):\n%s", diff) + } +} + +func TestDeleteWorker(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + worker := &ateapipb.Worker{ + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + } + + err := s.CreateWorker(ctx, worker) + if err != nil { + t.Fatalf("CreateWorker failed: %v", err) + } + + err = s.DeleteWorker(ctx, "default", "pool-1", "pod-1") + if err != nil { + t.Fatalf("DeleteWorker failed: %v", err) + } + + _, err = s.GetWorker(ctx, "default", "pool-1", "pod-1") + if !errors.Is(err, store.ErrNotFound) { + t.Errorf("expected ErrNotFound after delete, got %v", err) + } +} + +func TestDeleteActor(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor := &ateapipb.Actor{ + ActorId: "session-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "test-template", + Status: ateapipb.Actor_STATUS_SUSPENDED, + } + + err := s.CreateActor(ctx, actor) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + err = s.DeleteActor(ctx, "session-1") + if err != nil { + t.Fatalf("DeleteActor failed: %v", err) + } + + _, err = s.GetActor(ctx, "session-1") + if !errors.Is(err, store.ErrNotFound) { + t.Errorf("expected ErrNotFound after delete, got %v", err) + } +} + +func TestDeleteActor_NotSuspended(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor := &ateapipb.Actor{ + ActorId: "session-1", + ActorTemplateNamespace: "default", + ActorTemplateName: "test-template", + Status: ateapipb.Actor_STATUS_RUNNING, + } + + err := s.CreateActor(ctx, actor) + if err != nil { + t.Fatalf("CreateActor failed: %v", err) + } + + err = s.DeleteActor(ctx, "session-1") + if !errors.Is(err, store.ErrFailedPrecondition) { + t.Errorf("expected ErrFailedPrecondition deleting running actor, got %v", err) + } +} + +func TestDeleteActor_NotFound(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + err := s.DeleteActor(ctx, "non-existent") + if !errors.Is(err, store.ErrNotFound) { + t.Errorf("expected ErrNotFound deleting non-existent actor, got %v", err) + } +} + +func TestListWorkers(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + worker1 := &ateapipb.Worker{ + WorkerNamespace: "ns1", + WorkerPool: "pool1", + WorkerPod: "pod1", + } + worker2 := &ateapipb.Worker{ + WorkerNamespace: "ns1", + WorkerPool: "pool1", + WorkerPod: "pod2", + } + if err := s.CreateWorker(ctx, worker1); err != nil { + t.Fatalf("failed to create worker1: %v", err) + } + if err := s.CreateWorker(ctx, worker2); err != nil { + t.Fatalf("failed to create worker2: %v", err) + } + + workers, err := s.ListWorkers(ctx) + if err != nil { + t.Fatalf("ListWorkers failed: %v", err) + } + + if len(workers) != 2 { + t.Errorf("expected 2 workers, got %d", len(workers)) + } + + found1 := false + found2 := false + for _, w := range workers { + if w.GetWorkerPod() == "pod1" { + found1 = true + } + if w.GetWorkerPod() == "pod2" { + found2 = true + } + } + if !found1 || !found2 { + t.Errorf("did not find all workers: found1=%t, found2=%t", found1, found2) + } +} + +func TestListActors(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actor1 := &ateapipb.Actor{ + + ActorId: "id1", + ActorTemplateNamespace: "ns1", + ActorTemplateName: "tmpl1", + Status: ateapipb.Actor_STATUS_SUSPENDED, + LastSnapshot: "gs://b1/f1", + } + actor2 := &ateapipb.Actor{ + ActorId: "id2", + ActorTemplateNamespace: "ns1", + ActorTemplateName: "tmpl1", + Status: ateapipb.Actor_STATUS_SUSPENDED, + LastSnapshot: "gs://b1/f2", + } + + if err := s.CreateActor(ctx, actor1); err != nil { + t.Fatalf("failed to create actor1: %v", err) + } + if err := s.CreateActor(ctx, actor2); err != nil { + t.Fatalf("failed to create actor2: %v", err) + } + + actors, err := s.ListActors(ctx) + if err != nil { + t.Fatalf("ListActors failed: %v", err) + } + + if len(actors) != 2 { + t.Errorf("expected 2 actors, got %d", len(actors)) + } + + found1 := false + found2 := false + for _, a := range actors { + if a.GetActorId() == "id1" { + found1 = true + } + if a.GetActorId() == "id2" { + found2 = true + } + } + if !found1 || !found2 { + t.Errorf("did not find all actors: found1=%t, found2=%t", found1, found2) + } +} + +func TestUpdateWorker_Conflict(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + worker := &ateapipb.Worker{ + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + } + + err := s.CreateWorker(ctx, worker) + if err != nil { + t.Fatalf("CreateWorker failed: %v", err) + } + + // Fetch instance 1 + worker1, err := s.GetWorker(ctx, "default", "pool-1", "pod-1") + if err != nil { + t.Fatalf("GetWorker failed: %v", err) + } + + // Fetch instance 2 + worker2, err := s.GetWorker(ctx, "default", "pool-1", "pod-1") + if err != nil { + t.Fatalf("GetWorker failed: %v", err) + } + + // Update instance 1 + worker1.ActorId = "session-1" + err = s.UpdateWorker(ctx, worker1, worker1.Version) + if err != nil { + t.Fatalf("UpdateWorker failed: %v", err) + } + + // Try to update instance 2 + worker2.ActorId = "session-2" + err = s.UpdateWorker(ctx, worker2, worker2.Version) + if !errors.Is(err, store.ErrPersistenceRetry) { + t.Errorf("expected ErrPersistenceRetry, got %v", err) + } +} + +func TestCreateWorker_AlreadyExists(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + worker := &ateapipb.Worker{ + WorkerNamespace: "default", + WorkerPool: "pool-1", + WorkerPod: "pod-1", + } + + err := s.CreateWorker(ctx, worker) + if err != nil { + t.Fatalf("CreateWorker failed: %v", err) + } + + err = s.CreateWorker(ctx, worker) + if !errors.Is(err, store.ErrAlreadyExists) { + t.Errorf("expected ErrAlreadyExists, got %v", err) + } +} + +func TestListWorkers_Empty(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + workers, err := s.ListWorkers(ctx) + if err != nil { + t.Fatalf("ListWorkers failed: %v", err) + } + + if len(workers) != 0 { + t.Errorf("expected 0 workers, got %d", len(workers)) + } +} + +func TestListActors_Empty(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + actors, err := s.ListActors(ctx) + if err != nil { + t.Fatalf("ListActors failed: %v", err) + } + + if len(actors) != 0 { + t.Errorf("expected 0 actors, got %d", len(actors)) + } +} + +func TestAcquireLock_Success(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + key := "test-lock" + value := "token-1" + wrongValue := "token-2" + newValue := "token-3" + ttl := 10 * time.Second + + // 1. Acquire lock + acquired, err := s.AcquireLock(ctx, key, value, ttl) + if err != nil { + t.Fatalf("AcquireLock failed: %v", err) + } + if !acquired { + t.Errorf("expected lock to be acquired") + } + + // 2. Try to release with WRONG value + err = s.ReleaseLock(ctx, key, wrongValue) + if err != nil { + t.Fatalf("ReleaseLock failed: %v", err) + } + + // Verify it is STILL THERE by trying to acquire it again + acquired, err = s.AcquireLock(ctx, key, newValue, ttl) + if err != nil { + t.Fatalf("AcquireLock failed: %v", err) + } + if acquired { + t.Errorf("expected lock to still be held by token-1, but token-3 successfully acquired it!") + } + + // 3. Try to release with CORRECT value + err = s.ReleaseLock(ctx, key, value) + if err != nil { + t.Fatalf("ReleaseLock failed: %v", err) + } + + // Verify it is GONE by trying to acquire it again! + acquired, err = s.AcquireLock(ctx, key, newValue, ttl) + if err != nil { + t.Fatalf("AcquireLock failed: %v", err) + } + if !acquired { + t.Errorf("expected lock to be free, but it could not be acquired!") + } +} + +func TestAcquireLock_Conflict(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + key := "test-lock" + value1 := "token-1" + value2 := "token-2" + ttl := 10 * time.Second + + acquired, err := s.AcquireLock(ctx, key, value1, ttl) + if err != nil { + t.Fatalf("first AcquireLock failed: %v", err) + } + if !acquired { + t.Fatalf("expected first lock to be acquired") + } + + acquired, err = s.AcquireLock(ctx, key, value2, ttl) + if err != nil { + t.Fatalf("second AcquireLock failed: %v", err) + } + if acquired { + t.Errorf("expected second lock to fail (conflict)") + } +} + +func TestReleaseLock_Success(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + key := "test-lock" + value := "token-1" + ttl := 10 * time.Second + + s.AcquireLock(ctx, key, value, ttl) + + err := s.ReleaseLock(ctx, key, value) + if err != nil { + t.Fatalf("ReleaseLock failed: %v", err) + } + + // Verify it's gone + if mr.Exists(key) { + t.Errorf("expected lock to be deleted") + } +} + +func TestReleaseLock_Unsafe(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + key := "test-lock" + value1 := "token-1" + value2 := "token-2" + value3 := "token-3" + ttl := 10 * time.Second + + s.AcquireLock(ctx, key, value1, ttl) + + // Try to release with WRONG token + err := s.ReleaseLock(ctx, key, value2) + if err != nil { + t.Fatalf("ReleaseLock failed: %v", err) + } + + // Verify it is STILL THERE by trying to acquire it again! + acquired, err := s.AcquireLock(ctx, key, value3, ttl) + if err != nil { + t.Fatalf("AcquireLock failed: %v", err) + } + if acquired { + t.Errorf("expected lock to still be held by token-1, but token-3 successfully acquired it!") + } +} + +func TestAcquireLock_TTLExpiration(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + key := "test-lock" + value1 := "token-1" + value2 := "token-2" + ttl := 5 * time.Second + + // 1. Acquire lock + acquired, err := s.AcquireLock(ctx, key, value1, ttl) + if err != nil { + t.Fatalf("AcquireLock failed: %v", err) + } + if !acquired { + t.Fatalf("expected lock to be acquired") + } + + // 2. Fast-forward time past TTL + mr.FastForward(6 * time.Second) + + // 3. Try to acquire again with different token + acquired, err = s.AcquireLock(ctx, key, value2, ttl) + if err != nil { + t.Fatalf("AcquireLock failed: %v", err) + } + if !acquired { + t.Errorf("expected lock to be acquired by token-2 after TTL expiration") + } +} + +func TestAcquireLock_NonReentry(t *testing.T) { + mr, s, ctx := setupTest(t) + defer mr.Close() + + key := "test-lock" + value := "token-1" + ttl := 10 * time.Second + + // 1. Acquire lock first time + acquired, err := s.AcquireLock(ctx, key, value, ttl) + if err != nil { + t.Fatalf("first AcquireLock failed: %v", err) + } + if !acquired { + t.Fatalf("expected first lock to be acquired") + } + + // 2. Try to acquire lock again with SAME token + acquired, err = s.AcquireLock(ctx, key, value, ttl) + if err != nil { + t.Fatalf("second AcquireLock failed: %v", err) + } + if acquired { + t.Errorf("expected second lock acquisition to fail (non-reentrant)") + } +} diff --git a/cmd/servers/ateapi/store/store.go b/cmd/servers/ateapi/store/store.go new file mode 100644 index 000000000..ab76aa812 --- /dev/null +++ b/cmd/servers/ateapi/store/store.go @@ -0,0 +1,86 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package store contains common types for the persistence layer. +package store + +import ( + "context" + "errors" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +var ( + // ErrNotFound indicates that the given object is not present in the DB. + ErrNotFound = errors.New("persistence: not found") + + // ErrAlreadyExists indicates that the object already exists in the DB. + ErrAlreadyExists = errors.New("persistence: already exists") + + // ErrPersistenceRetry is the error returned when the persistence layer needs to retry. + ErrPersistenceRetry = errors.New("persistence: retry status") + + // ErrFailedPrecondition indicates the object is not in the required state for the operation. + ErrFailedPrecondition = errors.New("persistence: failed precondition") +) + +// Interface defines the contract for the persistence layer storing actor state. +type Interface interface { + // Fetches an actor by id. Returns ErrNotFound if missing. + GetActor(ctx context.Context, id string) (*ateapipb.Actor, error) + + // Stores a new actor in suspended state. Returns ErrAlreadyExists if key is taken. + CreateActor(ctx context.Context, actor *ateapipb.Actor) error + + // Updates actor state with optimistic concurrency check. Returns ErrNotFound if missing, or ErrPersistenceRetry on version mismatch. + UpdateActor(ctx context.Context, actor *ateapipb.Actor, expectedVersion int64) error + + // Removes an actor. Returns ErrNotFound if missing, or ErrFailedPrecondition if not suspended. + DeleteActor(ctx context.Context, id string) error + + // Lists all known actors. Returns nil if none found. + ListActors(ctx context.Context) ([]*ateapipb.Actor, error) + + // Fetches worker state by namespace, pool, and pod name. Returns ErrNotFound if missing. + GetWorker(ctx context.Context, namespace, pool, pod string) (*ateapipb.Worker, error) + + // Registers a new idle worker. Returns ErrAlreadyExists if already registered. + CreateWorker(ctx context.Context, worker *ateapipb.Worker) error + + // Updates worker state with optimistic concurrency check. Returns ErrNotFound if missing, or ErrPersistenceRetry on version mismatch. + UpdateWorker(ctx context.Context, worker *ateapipb.Worker, expectedVersion int64) error + + // Removes a worker. Idempotent: does nothing if worker is not found. + DeleteWorker(ctx context.Context, namespace, pool, pod string) error + + // Lists all known workers. Returns nil if none found. + ListWorkers(ctx context.Context) ([]*ateapipb.Worker, error) + + // AcquireLock attempts to acquire a distributed lock with a TTL. + // Returns true if the lock was successfully acquired. + // Returns false if the lock is already held by another client (conflict). + // Returns an error only on database failure. + // The value must be a unique token (e.g., UUID) to ensure safe release. + AcquireLock(ctx context.Context, key string, value string, ttl time.Duration) (bool, error) + + // ReleaseLock releases a distributed lock if the stored value matches the passed value. + // Returns nil if the lock was successfully released or if the lock was not held by this value. + // Returns an error only on database failure. + ReleaseLock(ctx context.Context, key string, value string) error + + // DebugClearAll drop all data from the database. Useful for debugging / local testing/ + DebugClearAll(ctx context.Context) error +} diff --git a/cmd/servers/ateapi/store/storetest/storetest.go b/cmd/servers/ateapi/store/storetest/storetest.go new file mode 100644 index 000000000..03cefa546 --- /dev/null +++ b/cmd/servers/ateapi/store/storetest/storetest.go @@ -0,0 +1,47 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package storetest + +import ( + "testing" + + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store" + "github.com/agent-substrate/substrate/cmd/servers/ateapi/store/ateredis" + "github.com/alicebob/miniredis/v2" + "github.com/redis/go-redis/v9" +) + +// SetupTestStore starts a miniredis server and returns a real store implementation +// backed by it, along with a cleanup function. +func SetupTestStore(t *testing.T) (store.Interface, func()) { + t.Helper() + + mr, err := miniredis.Run() + if err != nil { + t.Fatalf("failed to start miniredis: %v", err) + } + + rdb := redis.NewClusterClient(&redis.ClusterOptions{ + Addrs: []string{mr.Addr()}, + }) + + persistence := ateredis.NewPersistence(rdb) + + cleanup := func() { + mr.Close() + } + + return persistence, cleanup +} diff --git a/cmd/servers/atecontroller/main.go b/cmd/servers/atecontroller/main.go new file mode 100644 index 000000000..240712537 --- /dev/null +++ b/cmd/servers/atecontroller/main.go @@ -0,0 +1,107 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package main + +import ( + "crypto/tls" + "flag" + "os" + + clientv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/internal/controllers" + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + _ "k8s.io/client-go/plugin/pkg/client/auth" +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") + + ateAPIConnSpec = flag.String("ateapi-conn-spec", "dns:///api.ate-system.svc:443", "") +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(clientv1alpha1.AddToScheme(scheme)) // Register our CRD +} + +func main() { + ctrl.SetLogger(zap.New(zap.UseDevMode(true))) + + // TODO: Verify server certificate, pass client certificate. + clientTLSConfig := &tls.Config{ + InsecureSkipVerify: true, // Temporarily bypass standard checks + } + clientCreds := credentials.NewTLS(clientTLSConfig) + + ateapiConn, err := grpc.NewClient(*ateAPIConnSpec, grpc.WithTransportCredentials(clientCreds)) + if err != nil { + setupLog.Error(err, "Error creating grpc connection to ate api") + os.Exit(1) + } + + ateapiClient := ateapipb.NewControlClient(ateapiConn) + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + }) + if err != nil { + setupLog.Error(err, "unable to start manager") + os.Exit(1) + } + + if err = (&controllers.WorkerPoolReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "WorkerPool") + os.Exit(1) + } + + if err = (&controllers.ActorTemplateReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + AteClient: ateapiClient, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "ActorTemplate") + os.Exit(1) + } + + //+kubebuilder:scaffold:builder + + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + + setupLog.Info("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } +} diff --git a/cmd/servers/atelet/atelet.go b/cmd/servers/atelet/atelet.go new file mode 100644 index 000000000..2164c9999 --- /dev/null +++ b/cmd/servers/atelet/atelet.go @@ -0,0 +1,796 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "flag" + "fmt" + "log/slog" + "net" + "net/http" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + "time" + + "cloud.google.com/go/storage" + "github.com/agent-substrate/substrate/internal/ategcs" + "github.com/agent-substrate/substrate/internal/ateompath" + "github.com/agent-substrate/substrate/internal/memorypullcache" + "github.com/agent-substrate/substrate/proto/ateletpb" + "github.com/agent-substrate/substrate/proto/ateompb" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/google/go-containerregistry/pkg/authn" + googlecontainerauth "github.com/google/go-containerregistry/pkg/v1/google" + "github.com/prometheus/client_golang/prometheus/promhttp" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/prometheus" + "go.opentelemetry.io/otel/propagation" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "golang.org/x/sync/errgroup" + "google.golang.org/api/option" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/reflection" + "k8s.io/utils/lru" +) + +var ( + port = flag.Int("port", 8085, "The port to listen on") + metricsListenAddr = flag.String("metrics-listen-addr", ":9090", "Address and port the prometheus metrics server should listen on.") + + gcpAuthForImagePulls = flag.Bool("gcp-auth-for-image-pulls", true, "Use GCP application default credentials mechanism.") + localhostRegistryReplacement = flag.String("localhost-registry-replacement", "", "The replacement registry endpoint for localhost and/or loopback IP addresses, useful for local development. for example kind-registry:5000") +) + +func main() { + flag.Parse() + ctx := context.Background() + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil))) + + tp, err := initTracing(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to initialize tracing", slog.Any("err", err)) + os.Exit(1) + } + defer func() { + if err := tp.Shutdown(context.Background()); err != nil { + slog.Error("Failed to shutdown TracerProvider", slog.Any("err", err)) + } + }() + + mp, err := initMetrics(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to initialize metrics", slog.Any("err", err)) + os.Exit(1) + } + defer func() { + if err := mp.Shutdown(context.Background()); err != nil { + slog.Error("Failed to shutdown MeterProvider", slog.Any("err", err)) + } + }() + + go func() { + mux := http.NewServeMux() + mux.Handle("/metrics", promhttp.Handler()) + slog.InfoContext(ctx, fmt.Sprintf("Starting Prometheus metrics server on %s", *metricsListenAddr)) + if err := http.ListenAndServe(*metricsListenAddr, mux); err != nil { + slog.Error("Failed to start prometheus metrics server", slog.Any("err", err)) + } + }() + + ateomDialer := &AteomDialer{ + conns: lru.New(256), + } + + var gcpRegistryAuthn authn.Authenticator + if *gcpAuthForImagePulls { + gcpRegistryAuthn, err = googlecontainerauth.NewEnvAuthenticator(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to create GCP registry authenticator", slog.Any("err", err)) + os.Exit(1) + } + } + + pullCache, err := memorypullcache.NewMemoryPullCache(ctx, gcpRegistryAuthn, *localhostRegistryReplacement) + if err != nil { + slog.ErrorContext(ctx, "Failed to create pull cache", slog.Any("err", err)) + os.Exit(1) + } + + anonGCSClient, err := storage.NewClient(ctx, option.WithoutAuthentication()) + if err != nil { + slog.ErrorContext(ctx, "Failed to create anonymous GCS client", slog.Any("err", err)) + os.Exit(1) + } + + var gcsClient *storage.Client + var s3Client *s3.Client + storageBackend := os.Getenv("ATE_STORAGE_BACKEND") + switch storageBackend { + case "s3": + slog.InfoContext(ctx, "Using S3 storage backend") + // depend on standard AWS environment variables to configure the client + // these will need to be set on the atelet pods + cfg, err := config.LoadDefaultConfig(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to load S3 config", slog.Any("err", err)) + os.Exit(1) + } + s3Client = s3.NewFromConfig(cfg, func(o *s3.Options) { + if usePathStyle := os.Getenv("AWS_S3_USE_PATH_STYLE"); usePathStyle == "true" { + o.UsePathStyle = true + } + }) + // GCS is currently the default, TODO: we assume workload identity / ADC + default: + gcsClient, err = storage.NewClient(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to create GCS client", slog.Any("err", err)) + os.Exit(1) + } + } + + var wrappedAnonGCS ategcs.ObjectStorage + if anonGCSClient != nil { + wrappedAnonGCS = ategcs.NewGCSClient(anonGCSClient) + } + + var wrappedGCS ategcs.ObjectStorage + if s3Client != nil { + wrappedGCS = ategcs.NewS3Client(s3Client) + } else if gcsClient != nil { + wrappedGCS = ategcs.NewGCSClient(gcsClient) + } + + wmService := NewService( + ctx, + ateomDialer, + wrappedAnonGCS, + wrappedGCS, + pullCache, + ) + + lis, err := net.Listen("tcp", ":"+strconv.Itoa(*port)) + if err != nil { + slog.ErrorContext(ctx, "Failed to listen", slog.Any("err", err)) + os.Exit(1) + } + + svr := grpc.NewServer(grpc.StatsHandler(otelgrpc.NewServerHandler()), grpc.UnaryInterceptor(unaryInterceptor)) + ateletpb.RegisterAteomHerderServer(svr, wmService) + reflection.Register(svr) + slog.InfoContext(ctx, "WorkersManagerService listening", slog.Any("address", lis.Addr())) + if err := svr.Serve(lis); err != nil { + slog.ErrorContext(ctx, "Failed to serve", slog.Any("err", err)) + os.Exit(1) + } +} + +func unaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { + startTime := time.Now() + + resp, err := handler(ctx, req) + + slog.InfoContext(ctx, "Handle RPC", + slog.String("method", info.FullMethod), + slog.Any("req", req), + slog.Any("resp", resp), + slog.Any("err", err), + slog.String("elapsed-time", time.Since(startTime).String()), + ) + + return resp, err +} + +func initTracing(ctx context.Context) (*sdktrace.TracerProvider, error) { + exporter, err := otlptracegrpc.New(ctx, + // GKE managed traces doesn't support validating the TLS certs of the collector + otlptracegrpc.WithInsecure(), + ) + if err != nil { + return nil, fmt.Errorf("failed to create OTLP exporter: %w", err) + } + + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.ServiceName("atelet"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(res), + // Only trace on-demand when signaled by the client (e.g. via --trace flag) + sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.NeverSample())), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.TraceContext{}) + + return tp, nil +} + +func initMetrics(ctx context.Context) (*sdkmetric.MeterProvider, error) { + // Prometheus Exporter + promExporter, err := prometheus.New() + if err != nil { + return nil, fmt.Errorf("failed to create Prometheus metric exporter: %w", err) + } + + // OTLP Exporter + otlpExporter, err := otlpmetricgrpc.New(ctx, + otlpmetricgrpc.WithInsecure(), + ) + if err != nil { + return nil, fmt.Errorf("failed to create OTLP metric exporter: %w", err) + } + + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.ServiceName("atelet"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + mp := sdkmetric.NewMeterProvider( + // Register both readers + sdkmetric.WithReader(promExporter), + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(otlpExporter)), + sdkmetric.WithResource(res), + ) + otel.SetMeterProvider(mp) + + return mp, nil +} + +// AteomHerder is a service that allows controlling workloads on individual +// ateoms. +type AteomHerder struct { + ateletpb.UnimplementedAteomHerderServer + + ateomDialer *AteomDialer + pullCache *memorypullcache.MemoryPullCache + anonGCSClient ategcs.ObjectStorage + gcsClient ategcs.ObjectStorage +} + +var _ ateletpb.AteomHerderServer = (*AteomHerder)(nil) + +// NewService creates a new WorkersManagerService. +func NewService( + ctx context.Context, + ateomDialer *AteomDialer, + anonGCSClient ategcs.ObjectStorage, + gcsClient ategcs.ObjectStorage, + pullCache *memorypullcache.MemoryPullCache, +) *AteomHerder { + wms := &AteomHerder{ + ateomDialer: ateomDialer, + pullCache: pullCache, + anonGCSClient: anonGCSClient, + gcsClient: gcsClient, + } + return wms +} + +func (s *AteomHerder) fetchRunsc(ctx context.Context, cfg *ateletpb.RunscConfig) (string, error) { + var platCfg *ateletpb.RunscPlatformConfig + switch runtime.GOARCH { + case "amd64": + platCfg = cfg.GetAmd64() + case "arm64": + platCfg = cfg.GetArm64() + } + + localPath := ateompath.RunSCBinaryPath(platCfg.GetSha256Hash()) + _, err := os.Stat(localPath) + if err == nil { // EQUALS nil + return localPath, nil + } else if !errors.Is(err, os.ErrNotExist) { + return "", fmt.Errorf("while stat-ing local file: %w", err) + } + + // Fetch the file. + + client := s.anonGCSClient + if cfg.GetAuthentication().GetGcp().GetUse() { + client = s.gcsClient + } + + content, err := ategcs.FetchFromGCS(ctx, client, platCfg.GetUrl()) + if err != nil { + return "", fmt.Errorf("while fetching %v: %w", platCfg.GetUrl(), err) + } + + // Check hash + sum := sha256.Sum256(content) + wantSum, err := hex.DecodeString(platCfg.GetSha256Hash()) + if err != nil { + return "", fmt.Errorf("while parsing sha256 hash: %w", err) + } + if !bytes.Equal(sum[:], wantSum) { + return "", fmt.Errorf("sha256 mismatch; got=%s want=%s", hex.EncodeToString(sum[:]), platCfg.GetSha256Hash()) + } + + tmpFileName, err := func() (string, error) { + localDir := filepath.Dir(localPath) + tmpFile, err := os.CreateTemp(localDir, filepath.Base(localPath)+"-download-") + if err != nil { + return "", fmt.Errorf("while temp file: %w", err) + } + defer tmpFile.Close() + + if _, err := tmpFile.Write(content); err != nil { + return "", fmt.Errorf("while writing content to temp file: %w", err) + } + + if err := tmpFile.Chmod(0o755); err != nil { + return "", fmt.Errorf("while setting file mode: %w", err) + } + + return tmpFile.Name(), nil + }() + if err != nil { + return "", fmt.Errorf("while populating temp file: %w", err) + } + + if err := os.Rename(tmpFileName, localPath); err != nil { + return "", fmt.Errorf("while renaming temp file to target: %w", err) + } + + return localPath, nil +} + +func (s *AteomHerder) Run(ctx context.Context, req *ateletpb.RunRequest) (*ateletpb.RunResponse, error) { + // Create static files dir if it doesn't exist. + if err := os.MkdirAll(ateompath.StaticFilesDir, 0o700); err != nil { + return nil, fmt.Errorf("while creating static files dir: %w", err) + } + + // Download correct runsc version if not already downloaded. + runscPath, err := s.fetchRunsc(ctx, req.GetRunsc()) + if err != nil { + return nil, fmt.Errorf("in fetchRunsc: %w", err) + } + + // Clear actor state + if err := resetActorDirs(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()); err != nil { + return nil, fmt.Errorf("while resetting actor dirs: %w", err) + } + + netnsPath := ateompath.AteomNetNSPath(req.GetTargetAteomNamespace(), req.GetTargetAteomName()) + + g, gCtx := errgroup.WithContext(ctx) + + // Pull pause container and assemble OCI bundle + g.Go(func() error { + if err := prepareOCIDirectory( + gCtx, + s.pullCache, + req.GetActorTemplateNamespace(), + req.GetActorTemplateName(), + req.GetActorId(), + "pause", + req.GetSpec().GetPauseImage(), + []string{"/pause"}, + nil, + map[string]string{ + "io.kubernetes.cri.container-type": "sandbox", + "io.kubernetes.cri.container-name": "pause", + }, + netnsPath, + ); err != nil { + return fmt.Errorf("while creating pause OCI bundle: %w", err) + } + return nil + }) + + // Pull each application container and assemble OCI bundle + for _, ctr := range req.GetSpec().GetContainers() { + ctr := ctr + var envs []string + for _, env := range ctr.GetEnv() { + envs = append(envs, fmt.Sprintf("%s=%s", env.GetName(), env.GetValue())) + } + + g.Go(func() error { + if err := prepareOCIDirectory( + gCtx, + s.pullCache, + req.GetActorTemplateNamespace(), + req.GetActorTemplateName(), + req.GetActorId(), + ctr.GetName(), + ctr.GetImage(), + ctr.GetCommand(), + envs, + map[string]string{ + "io.kubernetes.cri.container-type": "container", + "io.kubernetes.cri.sandbox-id": "pause", + "io.kubernetes.cri.container-name": ctr.GetName(), + }, + netnsPath, + ); err != nil { + return fmt.Errorf("while creating %q OCI bundle: %w", ctr.GetName(), err) + } + return nil + }) + } + + if err := g.Wait(); err != nil { + return nil, err + } + + // Dial correct ateom over UDS. + ateomConn, err := s.ateomDialer.DialAteomPod(ctx, req.GetTargetAteomNamespace(), req.GetTargetAteomName()) + if err != nil { + return nil, fmt.Errorf("while getting ateom conn for %s/%s: %w", req.GetTargetAteomNamespace(), req.GetTargetAteomName(), err) + } + client := ateompb.NewAteomClient(ateomConn) + + // Tell ateom to do runsc create + runsc start for pause container and + // all application containers. + ateomReq := &ateompb.RunWorkloadRequest{ + ActorTemplateNamespace: req.GetActorTemplateNamespace(), + ActorTemplateName: req.GetActorTemplateName(), + ActorId: req.GetActorId(), + RunscPath: runscPath, + Spec: &ateompb.WorkloadSpec{}, + } + for _, ctr := range req.GetSpec().GetContainers() { + ateomCtr := &ateompb.Container{ + Name: ctr.GetName(), + } + ateomReq.GetSpec().Containers = append(ateomReq.GetSpec().Containers, ateomCtr) + } + _, err = client.RunWorkload(ctx, ateomReq) + if err != nil { + return nil, fmt.Errorf("while calling ateom.RunWorkload: %w", err) + } + + return &ateletpb.RunResponse{}, nil +} + +func (s *AteomHerder) Checkpoint(ctx context.Context, req *ateletpb.CheckpointRequest) (*ateletpb.CheckpointResponse, error) { + // Create static files dir if it doesn't exist. + if err := os.MkdirAll(ateompath.StaticFilesDir, 0o700); err != nil { + return nil, fmt.Errorf("while creating static files dir: %w", err) + } + + // Download correct runsc version if not already downloaded. + runscPath, err := s.fetchRunsc(ctx, req.GetRunsc()) + if err != nil { + return nil, fmt.Errorf("in fetchRunsc: %w", err) + } + + checkpointDir := ateompath.CheckpointDir(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()) + + // Dial correct ateom over UDS. + ateomConn, err := s.ateomDialer.DialAteomPod(ctx, req.GetTargetAteomNamespace(), req.GetTargetAteomName()) + if err != nil { + return nil, fmt.Errorf("while getting ateom conn for %s/%s: %w", req.GetTargetAteomNamespace(), req.GetTargetAteomName(), err) + } + client := ateompb.NewAteomClient(ateomConn) + + // TODO(ateom): Once we enable background restore, we need `runsc wait + // --restore pause` here, so that we know that gVisor is done with the + // restore checkpoint file. + + // Delete any existing checkpoint file left over from restore. + if err := os.RemoveAll(checkpointDir); err != nil { + return nil, fmt.Errorf("while deleting checkpoint: %w", err) + } + if err := os.MkdirAll(checkpointDir, 0o700); err != nil { + return nil, fmt.Errorf("while creating checkpoint dir: %w", err) + } + + // Tell ateom to take checkpoint and delete containers. + ateomReq := &ateompb.CheckpointWorkloadRequest{ + ActorTemplateNamespace: req.GetActorTemplateNamespace(), + ActorTemplateName: req.GetActorTemplateName(), + ActorId: req.GetActorId(), + RunscPath: runscPath, + Spec: &ateompb.WorkloadSpec{}, + } + for _, ctr := range req.GetSpec().GetContainers() { + ateomCtr := &ateompb.Container{ + Name: ctr.GetName(), + } + ateomReq.GetSpec().Containers = append(ateomReq.GetSpec().Containers, ateomCtr) + } + _, err = client.CheckpointWorkload(ctx, ateomReq) + if err != nil { + return nil, fmt.Errorf("while calling ateom.CheckpointWorkload: %w", err) + } + + // Upload checkpoint from local dir. + err = ategcs.SendLocalFileToGCSWithZstd( + ctx, + s.gcsClient, + strings.TrimSuffix(req.GetSnapshotUriPrefix(), "/")+"/checkpoint.img.zstd", + ateompath.CheckpointImgPath(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()), + ) + if err != nil { + return nil, fmt.Errorf("while uploading checkpoint.img to GCS: %w", err) + } + + pagesImgPath := ateompath.PagesImgPath(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()) + if _, err := os.Stat(pagesImgPath); err == nil { // EQUALS nil + err = ategcs.SendLocalFileToGCSWithZstd( + ctx, + s.gcsClient, + strings.TrimSuffix(req.GetSnapshotUriPrefix(), "/")+"/pages.img.zstd", + pagesImgPath, + ) + if err != nil { + return nil, fmt.Errorf("while uploading pages.img to GCS: %w", err) + } + } + + pagesMetaImgPath := ateompath.PagesMetaImgPath(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()) + if _, err := os.Stat(pagesMetaImgPath); err == nil { // EQUALS nil + err = ategcs.SendLocalFileToGCSWithZstd( + ctx, + s.gcsClient, + strings.TrimSuffix(req.GetSnapshotUriPrefix(), "/")+"/pages_meta.img.zstd", + pagesMetaImgPath, + ) + if err != nil { + return nil, fmt.Errorf("while uploading pages_meta.img to GCS: %w", err) + } + } + + // Clear actor state + if err := resetActorDirs(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()); err != nil { + return nil, fmt.Errorf("while resetting actor dirs: %w", err) + } + + return &ateletpb.CheckpointResponse{}, nil +} + +func (s *AteomHerder) Restore(ctx context.Context, req *ateletpb.RestoreRequest) (*ateletpb.RestoreResponse, error) { + // Create static files dir if it doesn't exist. + if err := os.MkdirAll(ateompath.StaticFilesDir, 0o700); err != nil { + return nil, fmt.Errorf("while creating static files dir: %w", err) + } + + // Download correct runsc version if not already downloaded. + runscPath, err := s.fetchRunsc(ctx, req.GetRunsc()) + if err != nil { + return nil, fmt.Errorf("in fetchRunsc: %w", err) + } + + // Clear actor state + if err := resetActorDirs(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()); err != nil { + return nil, fmt.Errorf("while resetting actor dirs: %w", err) + } + + g, gCtx := errgroup.WithContext(ctx) + + g.Go(func() error { + if err := ategcs.FetchLocalFileFromGCSWithZstd( + gCtx, + s.gcsClient, + strings.TrimSuffix(req.GetSnapshotUriPrefix(), "/")+"/checkpoint.img.zstd", + ateompath.CheckpointImgPath(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()), + ); err != nil { + return fmt.Errorf("while downloading checkpoint.img from GCS: %w", err) + } + return nil + }) + + g.Go(func() error { + if err := ategcs.FetchLocalFileFromGCSWithZstd( + gCtx, + s.gcsClient, + strings.TrimSuffix(req.GetSnapshotUriPrefix(), "/")+"/pages.img.zstd", + ateompath.PagesImgPath(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()), + ); err != nil { + return fmt.Errorf("while downloading pages.img from GCS: %w", err) + } + return nil + }) + + g.Go(func() error { + if err := ategcs.FetchLocalFileFromGCSWithZstd( + gCtx, + s.gcsClient, + strings.TrimSuffix(req.GetSnapshotUriPrefix(), "/")+"/pages_meta.img.zstd", + ateompath.PagesMetaImgPath(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()), + ); err != nil { + return fmt.Errorf("while downloading pages_meta.img from GCS: %w", err) + } + return nil + }) + + if err := g.Wait(); err != nil { + return nil, err + } + + netnsPath := ateompath.AteomNetNSPath(req.GetTargetAteomNamespace(), req.GetTargetAteomName()) + + g, gCtx = errgroup.WithContext(ctx) + + // Pull pause container and assemble OCI bundle + g.Go(func() error { + if err := prepareOCIDirectory( + gCtx, + s.pullCache, + req.GetActorTemplateNamespace(), + req.GetActorTemplateName(), + req.GetActorId(), + "pause", + req.GetSpec().GetPauseImage(), + []string{"/pause"}, + nil, + map[string]string{ + "io.kubernetes.cri.container-type": "sandbox", + "io.kubernetes.cri.container-name": "pause", + }, + netnsPath, + ); err != nil { + return fmt.Errorf("while creating pause OCI bundle: %w", err) + } + return nil + }) + + // Pull each application container and assemble OCI bundle + for _, ctr := range req.GetSpec().GetContainers() { + ctr := ctr + var envs []string + for _, env := range ctr.GetEnv() { + envs = append(envs, fmt.Sprintf("%s=%s", env.GetName(), env.GetValue())) + } + + g.Go(func() error { + if err := prepareOCIDirectory( + gCtx, + s.pullCache, + req.GetActorTemplateNamespace(), + req.GetActorTemplateName(), + req.GetActorId(), + ctr.GetName(), + ctr.GetImage(), + ctr.GetCommand(), + envs, + map[string]string{ + "io.kubernetes.cri.container-type": "container", + "io.kubernetes.cri.sandbox-id": "pause", + "io.kubernetes.cri.container-name": ctr.GetName(), + }, + netnsPath, + ); err != nil { + return fmt.Errorf("while creating %q OCI bundle: %w", ctr.GetName(), err) + } + return nil + }) + } + + if err := g.Wait(); err != nil { + return nil, err + } + + // Dial correct ateom over UDS. + ateomConn, err := s.ateomDialer.DialAteomPod(ctx, req.GetTargetAteomNamespace(), req.GetTargetAteomName()) + if err != nil { + return nil, fmt.Errorf("while getting ateom conn for %s/%s: %w", req.GetTargetAteomNamespace(), req.GetTargetAteomName(), err) + } + client := ateompb.NewAteomClient(ateomConn) + + // Tell ateom to do runsc create + runsc restore for pause container and + // all application containers. + ateomReq := &ateompb.RestoreWorkloadRequest{ + ActorTemplateNamespace: req.GetActorTemplateNamespace(), + ActorTemplateName: req.GetActorTemplateName(), + ActorId: req.GetActorId(), + RunscPath: runscPath, + Spec: &ateompb.WorkloadSpec{}, + } + for _, ctr := range req.GetSpec().GetContainers() { + ateomCtr := &ateompb.Container{ + Name: ctr.GetName(), + } + ateomReq.GetSpec().Containers = append(ateomReq.GetSpec().Containers, ateomCtr) + } + _, err = client.RestoreWorkload(ctx, ateomReq) + if err != nil { + return nil, fmt.Errorf("while calling ateom.RestoreWorkload: %w", err) + } + + return &ateletpb.RestoreResponse{}, nil +} + +type AteomDialer struct { + conns *lru.Cache +} + +func (d *AteomDialer) DialAteomPod(ctx context.Context, namespace, name string) (*grpc.ClientConn, error) { + key := namespace + "/" + name + + connAny, ok := d.conns.Get(key) + if ok { + return connAny.(*grpc.ClientConn), nil + } + + conn, err := grpc.NewClient( + "unix://"+ateompath.AteomSocketPath(namespace, name), + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithStatsHandler(otelgrpc.NewClientHandler()), + ) + if err != nil { + return nil, fmt.Errorf("while creating atelet gRPC client connection: %w", err) + } + + d.conns.Add(key, conn) + + return conn, nil +} + +func resetActorDirs(actorTemplateNamespace, actorTemplateName, actorID string) error { + // Explicitly leave runsc logs dir untouched. + + bundleDir := ateompath.OCIBundleDir(actorTemplateNamespace, actorTemplateName, actorID) + if err := os.RemoveAll(bundleDir); err != nil { + return fmt.Errorf("while deleting bundle dir: %w", err) + } + if err := os.MkdirAll(bundleDir, 0o700); err != nil { + return fmt.Errorf("while creating bundle dir: %w", err) + } + + runscDir := ateompath.RunSCStateDir(actorTemplateNamespace, actorTemplateName, actorID) + if err := os.RemoveAll(runscDir); err != nil { + return fmt.Errorf("while deleting runsc state dir: %w", err) + } + if err := os.MkdirAll(runscDir, 0o700); err != nil { + return fmt.Errorf("while creating runsc state dir: %w", err) + } + + pidFileDir := ateompath.PIDFileDir(actorTemplateNamespace, actorTemplateName, actorID) + if err := os.RemoveAll(pidFileDir); err != nil { + return fmt.Errorf("while deleting PID file dir: %w", err) + } + if err := os.MkdirAll(pidFileDir, 0o700); err != nil { + return fmt.Errorf("while creating PID file dir: %w", err) + } + + checkpointDir := ateompath.CheckpointDir(actorTemplateNamespace, actorTemplateName, actorID) + if err := os.RemoveAll(checkpointDir); err != nil { + return fmt.Errorf("while deleting checkpoint dir: %w", err) + } + if err := os.MkdirAll(checkpointDir, 0o700); err != nil { + return fmt.Errorf("while creating checkpoint dir: %w", err) + } + + return nil +} diff --git a/cmd/servers/atelet/oci.go b/cmd/servers/atelet/oci.go new file mode 100644 index 000000000..a2ae14c0a --- /dev/null +++ b/cmd/servers/atelet/oci.go @@ -0,0 +1,281 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "archive/tar" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "log/slog" + "os" + "path" + "path/filepath" + + "github.com/agent-substrate/substrate/internal/ateompath" + "github.com/agent-substrate/substrate/internal/memorypullcache" + "github.com/opencontainers/runtime-spec/specs-go" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" +) + +func prepareOCIDirectory(ctx context.Context, pullCache *memorypullcache.MemoryPullCache, actorTemplateNamespace, actorTemplateName, actorID, containerName, ref string, args []string, env []string, annotations map[string]string, netns string) error { + tracer := otel.Tracer("prepareOCIDirectory") + + ctx, span := tracer.Start(ctx, "prepareOCIDirectory") + span.SetAttributes(attribute.String("image", ref)) + defer span.End() + + bundlePath := ateompath.OCIBundlePath(actorTemplateNamespace, actorTemplateName, actorID, containerName) + rootPath := path.Join(bundlePath, "rootfs") + + if err := os.RemoveAll(rootPath); err != nil { + return fmt.Errorf("while clearing rootfs %q: %w", rootPath, err) + } + + if err := os.MkdirAll(rootPath, 0o700); err != nil { + return fmt.Errorf("in os.MkdirAll for container bundle dir: %w", err) + } + + tarData, err := pullCache.Fetch(ctx, ref) + if err != nil { + return fmt.Errorf("in pullCache.Fetch: %w", err) + } + defer tarData.Close() + + if err := untar(ctx, tarData, rootPath); err != nil { + return fmt.Errorf("in untar: %w", err) + } + + envVars := []string{ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + } + envVars = append(envVars, env...) + + ociSpec := &specs.Spec{ + Process: &specs.Process{ + User: specs.User{ + UID: 0, + GID: 0, + }, + Args: args, + Env: envVars, + Cwd: "/", + Capabilities: &specs.LinuxCapabilities{ + Bounding: []string{ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE", + }, + Effective: []string{ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE", + }, + Inheritable: []string{ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE", + }, + Permitted: []string{ + "CAP_AUDIT_WRITE", + "CAP_KILL", + "CAP_NET_BIND_SERVICE", + }, + // TODO(gvisor.dev/issue/3166): support ambient capabilities + }, + Rlimits: []specs.POSIXRlimit{ + { + Type: "RLIMIT_NOFILE", + Hard: 1024, + Soft: 1024, + }, + }, + }, + Root: &specs.Root{ + Path: "rootfs", + Readonly: false, + }, + Hostname: "runsc", + Mounts: []specs.Mount{ + { + Destination: "/proc", + Type: "proc", + Source: "proc", + }, + { + Destination: "/dev", + Type: "tmpfs", + Source: "tmpfs", + }, + { + Destination: "/sys", + Type: "sysfs", + Source: "sysfs", + Options: []string{ + "nosuid", + "noexec", + "nodev", + "ro", + }, + }, + { + Destination: "/etc/resolv.conf", + Type: "bind", + Source: "/etc/resolv.conf", + Options: []string{"ro"}, + }, + }, + Linux: &specs.Linux{ + Namespaces: []specs.LinuxNamespace{ + { + Type: "pid", + }, + { + Type: "network", + Path: netns, // Will be created by ateom + }, + { + Type: "ipc", + }, + { + Type: "uts", + }, + { + Type: "mount", + }, + }, + }, + Annotations: annotations, + } + ociSpecBytes, err := json.MarshalIndent(ociSpec, "", " ") + if err != nil { + return fmt.Errorf("while marshaling OCI spec: %w", err) + } + specPath := path.Join(bundlePath, "config.json") + if err := os.WriteFile(specPath, ociSpecBytes, 0o600); err != nil { + return fmt.Errorf("while writing OCI spec: %w", err) + } + + return nil +} + +func untar(ctx context.Context, tarData io.Reader, rootPath string) error { + tracer := otel.Tracer("ateom-gvisor") + ctx, span := tracer.Start(ctx, "untar") + defer span.End() + + tarReader := tar.NewReader(tarData) + for { + hdr, err := tarReader.Next() + if errors.Is(err, io.EOF) { + break + } else if err != nil { + return fmt.Errorf("in tarReader.Next: %w", err) + } + + switch hdr.Typeflag { + case tar.TypeReg: // Regular file + target := filepath.Join(rootPath, hdr.Name) + + // Stream directly from tarReader to target file to avoid buffering in memory. + outFile, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR|os.O_TRUNC, hdr.FileInfo().Mode()) + if err != nil { + return fmt.Errorf("while creating file %q: %w", target, err) + } + + // TODO: Use a constrained fs so that paths containing `..` cannot + // end up outside the root, and symlinks / hardlinks cannot point + // outside the root. + _, err = io.Copy(outFile, tarReader) + closeErr := outFile.Close() + + if err != nil { + return fmt.Errorf("while writing contents of %q from tar stream: %w", hdr.Name, err) + } + if closeErr != nil { + return fmt.Errorf("while closing file %q: %w", target, closeErr) + } + + case tar.TypeDir: + if hdr.Name == "." { + // Huh? I guess this is for setting mode, etc on the root + // folder. Ignore for now. + continue + } + target := filepath.Join(rootPath, hdr.Name) + err := os.Mkdir(target, hdr.FileInfo().Mode()) + if errors.Is(err, os.ErrExist) { + // Ignore --- real images produced by ko seem to have directory entries placed multiple times? + } else if err != nil { + return fmt.Errorf("while creating directory=%q, mode=%v: %w", target, hdr.FileInfo().Mode(), err) + } + + case tar.TypeSymlink: + // TODO: Make sure no tricky people are trying to create a symlink pointing out of the rootfs. + source := filepath.Join(rootPath, hdr.Name) + // OCI image layers may re-define the same path across layers (e.g. + // an earlier layer creates /var/run as a directory and a later + // layer re-declares it as a symlink to /run). Standard tar-extract + // semantics are "later entry wins": replace any existing entry. + if existing, err := os.Lstat(source); err == nil { + // If it's already the same symlink, skip the unlink+symlink pair. + if existing.Mode()&os.ModeSymlink != 0 { + if cur, rerr := os.Readlink(source); rerr == nil && cur == hdr.Linkname { + continue + } + } + // os.RemoveAll removes the symlink entry itself; it does NOT + // traverse and remove the directory the symlink points to. + // That's the desired semantic here — replace this path's + // entry without touching whatever the prior symlink targeted. + if err := os.RemoveAll(source); err != nil { + return fmt.Errorf("while replacing existing path at %q before symlink: %w", source, err) + } + } else if !errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("while checking existing path at %q before symlink: %w", source, err) + } + if err := os.Symlink(hdr.Linkname, source); err != nil { + return fmt.Errorf("while creating symlink src=%q target=%q: %w", source, hdr.Linkname, err) + } + + case tar.TypeLink: + // TODO: Make sure no tricky people are trying to create a hardlink pointing out of the rootfs. + source := filepath.Join(rootPath, hdr.Linkname) + target := filepath.Join(rootPath, hdr.Name) + // Same "later entry wins" handling as TypeSymlink: replace existing entry. + if _, err := os.Lstat(target); err == nil { + if err := os.RemoveAll(target); err != nil { + return fmt.Errorf("while replacing existing path at %q before hardlink: %w", target, err) + } + } else if !errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("while checking existing path at %q before hardlink: %w", target, err) + } + if err := os.Link(source, target); err != nil { + return fmt.Errorf("while creating hardlink src=%q target=%q: %w", source, target, err) + } + + default: + tfStr := string([]byte{hdr.Typeflag}) + slog.ErrorContext(ctx, "Unhandled tar entry typeflag", slog.String("typeflag", tfStr), slog.Any("hdr", hdr)) + return fmt.Errorf("unhandled tar entry typeflag %q", tfStr) + } + + } + + return nil +} diff --git a/cmd/servers/atenet/app/dns/cmd.go b/cmd/servers/atenet/app/dns/cmd.go new file mode 100644 index 000000000..da93573f3 --- /dev/null +++ b/cmd/servers/atenet/app/dns/cmd.go @@ -0,0 +1,106 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dns + +import ( + "context" + "fmt" + "log/slog" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "github.com/agent-substrate/substrate/internal/dns" + "github.com/spf13/cobra" + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" +) + +type DnsConfig struct { + LogLevel string + Kubeconfig string + ReconcileInterval time.Duration + CorefilePath string +} + +func NewCmd() *cobra.Command { + var cfg DnsConfig + + cmd := &cobra.Command{ + Use: "dns", + Short: "Orchestrates CoreDNS and GKE stub resolver configuration", + RunE: func(cmd *cobra.Command, args []string) error { + ctx, cancel := context.WithCancel(cmd.Context()) + defer cancel() + + var level slog.Level + switch strings.ToLower(cfg.LogLevel) { + case "debug": + level = slog.LevelDebug + case "warn": + level = slog.LevelWarn + case "error": + level = slog.LevelError + default: + level = slog.LevelInfo + } + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: level}))) + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + go func() { + <-sigChan + cancel() + }() + + k8sCfg, err := config.GetConfig() + if err != nil { + if cfg.Kubeconfig != "" { + k8sCfg, err = clientcmd.BuildConfigFromFlags("", cfg.Kubeconfig) + if err != nil { + return fmt.Errorf("failed to read config from path %s: %w", cfg.Kubeconfig, err) + } + } else { + return fmt.Errorf("unable to establish Kubernetes configuration parameters: %w", err) + } + } + + k8sClient, err := client.New(k8sCfg, client.Options{}) + if err != nil { + return fmt.Errorf("failed to initialize cluster client: %w", err) + } + + dnsController := &dns.Controller{ + Client: k8sClient, + Interval: cfg.ReconcileInterval, + CorefilePath: cfg.CorefilePath, + Reloader: dns.NewConfigReloader(), + } + + slog.InfoContext(ctx, "Starting DNS Controller subsystem") + return dnsController.Run(ctx) + }, + } + + cmd.Flags().StringVar(&cfg.LogLevel, "log-level", "info", "Log level: debug, info, warn, error") + cmd.Flags().StringVar(&cfg.Kubeconfig, "kubeconfig", "", "Absolute path to the kubeconfig configuration file") + cmd.Flags().DurationVar(&cfg.ReconcileInterval, "interval", 10*time.Second, "Interval for reconciling DNS configurations") + cmd.Flags().StringVar(&cfg.CorefilePath, "corefile-path", "/etc/coredns/Corefile", "Path to the local Corefile configuration on shared volume") + + return cmd +} diff --git a/cmd/servers/atenet/app/root.go b/cmd/servers/atenet/app/root.go new file mode 100644 index 000000000..7cae015d2 --- /dev/null +++ b/cmd/servers/atenet/app/root.go @@ -0,0 +1,42 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package app + +import ( + "fmt" + "os" + + "github.com/agent-substrate/substrate/cmd/servers/atenet/app/dns" + "github.com/agent-substrate/substrate/cmd/servers/atenet/app/router" + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "atenet", + Short: "atenet is a combined daemon for all networking functionality.", + Long: `atenet is a combined daemon for all networking functionality.`, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + rootCmd.AddCommand(router.NewCmd()) + rootCmd.AddCommand(dns.NewCmd()) +} diff --git a/cmd/servers/atenet/app/router/atstore.go b/cmd/servers/atenet/app/router/atstore.go new file mode 100644 index 000000000..7684ee7be --- /dev/null +++ b/cmd/servers/atenet/app/router/atstore.go @@ -0,0 +1,55 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "fmt" + + v1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// atStore defines an interface for retrieving a collection of ActorTemplates. +type atStore interface { + readyTemplates(ctx context.Context) ([]*v1alpha1.ActorTemplate, error) +} + +// k8sATStore implements the atStore interface using a Kubernetes client. +type k8sATStore struct { + k8sClient client.Client +} + +func newk8sATStore(k8sClient client.Client) *k8sATStore { + return &k8sATStore{ + k8sClient: k8sClient, + } +} + +func (t *k8sATStore) readyTemplates(ctx context.Context) ([]*v1alpha1.ActorTemplate, error) { + var atList v1alpha1.ActorTemplateList + if err := t.k8sClient.List(ctx, &atList); err != nil { + return nil, fmt.Errorf("failed to list ActorTemplates: %w", err) + } + + var templates []*v1alpha1.ActorTemplate + for i := range atList.Items { + if atList.Items[i].Status.Phase != v1alpha1.PhaseReady { + continue + } + templates = append(templates, &atList.Items[i]) + } + return templates, nil +} diff --git a/cmd/servers/atenet/app/router/atstore_file.go b/cmd/servers/atenet/app/router/atstore_file.go new file mode 100644 index 000000000..cd3190e85 --- /dev/null +++ b/cmd/servers/atenet/app/router/atstore_file.go @@ -0,0 +1,130 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "log/slog" + "os" + "strings" + + v1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "k8s.io/apimachinery/pkg/util/yaml" + sigsyaml "sigs.k8s.io/yaml" +) + +// fileATStore implements the atStore interface by reading and decoding YAML or JSON +// files containing ActorTemplates or ActorTemplateLists. +type fileATStore struct { + filePath string +} + +func newFileATStore(filePath string) *fileATStore { + return &fileATStore{ + filePath: filePath, + } +} + +func (t *fileATStore) readyTemplates(ctx context.Context) ([]*v1alpha1.ActorTemplate, error) { + data, err := os.ReadFile(t.filePath) + if err != nil { + return nil, fmt.Errorf("failed to read actor templates YAML file %q: %w", t.filePath, err) + } + + decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(data), 4096) + var templates []*v1alpha1.ActorTemplate + + for { + var obj map[string]interface{} + if err := decoder.Decode(&obj); err != nil { + if err == io.EOF { + break + } + return nil, fmt.Errorf("failed to decode YAML document: %w", err) + } + + if obj == nil { + continue + } + + // Check if it's a List (e.g., standard kubectl get -o yaml output) + if kind, ok := obj["kind"].(string); ok && strings.EqualFold(kind, "List") { + items, ok := obj["items"].([]interface{}) + if !ok { + continue + } + + for _, itemVal := range items { + itemMap, ok := itemVal.(map[string]interface{}) + if !ok { + continue + } + + itemBytes, err := json.Marshal(itemMap) + if err != nil { + return nil, fmt.Errorf("failed to marshal item to JSON: %w", err) + } + + var item v1alpha1.ActorTemplate + if err := sigsyaml.Unmarshal(itemBytes, &item); err != nil { + return nil, fmt.Errorf("failed to unmarshal ActorTemplate item: %w", err) + } + + templates = append(templates, &item) + } + continue + } + + // It's an ActorTemplateList structure + if kind, ok := obj["kind"].(string); ok && strings.EqualFold(kind, "ActorTemplateList") { + objBytes, err := json.Marshal(obj) + if err != nil { + return nil, fmt.Errorf("failed to marshal ActorTemplateList to JSON: %w", err) + } + + var list v1alpha1.ActorTemplateList + if err := sigsyaml.Unmarshal(objBytes, &list); err != nil { + return nil, fmt.Errorf("failed to unmarshal ActorTemplateList: %w", err) + } + + for i := range list.Items { + templates = append(templates, &list.Items[i]) + } + continue + } + + // Fallback: single ActorTemplate document + objBytes, err := json.Marshal(obj) + if err != nil { + return nil, fmt.Errorf("failed to marshal document to JSON: %w", err) + } + + var item v1alpha1.ActorTemplate + if err := sigsyaml.Unmarshal(objBytes, &item); err != nil { + return nil, fmt.Errorf("failed to unmarshal document as ActorTemplate: %w", err) + } + + templates = append(templates, &item) + } + + slog.InfoContext(ctx, "fileATStore parsed offline templates", + slog.String("filePath", t.filePath), + slog.Int("count", len(templates))) + return templates, nil +} diff --git a/cmd/servers/atenet/app/router/atstore_test.go b/cmd/servers/atenet/app/router/atstore_test.go new file mode 100644 index 000000000..ab82157cf --- /dev/null +++ b/cmd/servers/atenet/app/router/atstore_test.go @@ -0,0 +1,143 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "os" + "path/filepath" + "testing" +) + +func TestFileATStore(t *testing.T) { + tmpDir := t.TempDir() + + singleTmpl := ` +apiVersion: substrate.storage.ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: single-actor + namespace: default +spec: + snapshotsConfig: + location: "gs://test-bucket/snapshots" + workerPoolRef: + name: pool-1 +` + + multiTmpl := ` +apiVersion: substrate.storage.ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: actor-a + namespace: prod +spec: + snapshotsConfig: + location: "gs://prod-bucket/a" + workerPoolRef: + name: heavy-pool +--- +apiVersion: substrate.storage.ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: actor-b + namespace: prod +spec: + snapshotsConfig: + location: "gs://prod-bucket/b" + workerPoolRef: + name: light-pool +` + + listTmpl := ` +apiVersion: v1 +kind: List +items: +- apiVersion: substrate.storage.ate.dev/v1alpha1 + kind: ActorTemplate + metadata: + name: list-a + namespace: dev + spec: + snapshotsConfig: + location: "gs://dev-bucket/a" + workerPoolRef: + name: dev-pool +- apiVersion: substrate.storage.ate.dev/v1alpha1 + kind: ActorTemplate + metadata: + name: list-b + namespace: dev + spec: + snapshotsConfig: + location: "gs://dev-bucket/b" + workerPoolRef: + name: dev-pool +` + + tests := []struct { + name string + yamlContent string + wantCount int + wantNames []string + }{ + { + name: "Single Document", + yamlContent: singleTmpl, + wantCount: 1, + wantNames: []string{"single-actor"}, + }, + { + name: "Multi Document Stream", + yamlContent: multiTmpl, + wantCount: 2, + wantNames: []string{"actor-a", "actor-b"}, + }, + { + name: "List structure", + yamlContent: listTmpl, + wantCount: 2, + wantNames: []string{"list-a", "list-b"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + filePath := filepath.Join(tmpDir, tt.name+".yaml") + if err := os.WriteFile(filePath, []byte(tt.yamlContent), 0644); err != nil { + t.Fatalf("failed to create test file: %v", err) + } + + store := newFileATStore(filePath) + templates, err := store.readyTemplates(context.Background()) + if err != nil { + t.Fatalf("Templates() error: %v", err) + } + + if len(templates) != tt.wantCount { + t.Errorf("got %d items, expected %d", len(templates), tt.wantCount) + } + + for i, wantName := range tt.wantNames { + if i >= len(templates) { + break + } + if templates[i].Name != wantName { + t.Errorf("item %d name = %q, expected %q", i, templates[i].Name, wantName) + } + } + }) + } +} diff --git a/cmd/servers/atenet/app/router/controller.go b/cmd/servers/atenet/app/router/controller.go new file mode 100644 index 000000000..055751fbe --- /dev/null +++ b/cmd/servers/atenet/app/router/controller.go @@ -0,0 +1,110 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "log/slog" + "time" + + "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// Controller monitors ActorTemplates and coordinates configuration updates +// for the Envoy xDS and external processing servers. +type Controller struct { + k8sClient client.Client + clientset kubernetes.Interface + cfg RouterConfig + xdsSrv *XdsServer + extprocSrv *ExtProcServer + + atStore atStore + envoyRunner *envoyrunner +} + +func NewController( + k8sClient client.Client, + clientset kubernetes.Interface, + cfg RouterConfig, + xdsSrv *XdsServer, + extprocSrv *ExtProcServer, +) *Controller { + xdsSrv.SetConfig(cfg.HttpPort, cfg.ExtprocPort, cfg.ExtprocAddr) + + var store atStore + if cfg.TemplatesFile != "" { + store = newFileATStore(cfg.TemplatesFile) + } else { + store = newk8sATStore(k8sClient) + } + + return &Controller{ + k8sClient: k8sClient, + clientset: clientset, + cfg: cfg, + xdsSrv: xdsSrv, + extprocSrv: extprocSrv, + + atStore: store, + envoyRunner: newEnvoyRunner(k8sClient, cfg), + } +} + +func (c *Controller) Start(ctx context.Context) error { + // Run first reconcile eagerly on startup + if err := c.reconcile(ctx); err != nil { + slog.ErrorContext(ctx, "Error during initial eager router reconciliation", slog.String("err", err.Error())) + } + + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return nil + case <-ticker.C: + if err := c.reconcile(ctx); err != nil { + slog.ErrorContext(ctx, "Error during router reconciliation", slog.String("err", err.Error())) + } + } + } +} + +func (c *Controller) reconcile(ctx context.Context) error { + _, err := c.atStore.readyTemplates(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to get ActorTemplates", slog.String("err", err.Error())) + return err + } + + if err := c.xdsSrv.UpdateSnapshot(); err != nil { + slog.ErrorContext(ctx, "xDS Configuration generation problem", slog.String("err", err.Error())) + return err + } + + if !c.cfg.Standalone && c.cfg.TemplatesFile == "" { + // Reconcile Envoy router Deployment and Kubernetes cluster entities + err := c.envoyRunner.reconcile(ctx) + if err != nil { + slog.ErrorContext(ctx, "Error during Envoy router reconciliation", slog.String("err", err.Error())) + return err + } + } + + return nil +} diff --git a/cmd/servers/atenet/app/router/dashboard.html b/cmd/servers/atenet/app/router/dashboard.html new file mode 100644 index 000000000..083d0d019 --- /dev/null +++ b/cmd/servers/atenet/app/router/dashboard.html @@ -0,0 +1,458 @@ + + + + + + + atenet Router Status Dashboard + + + + +
+
+
+
+

atenet Router Status

+
+
+ + Build: {{ .BuildTag }} +
+
+ +
+
+
Infrastructure details
+ + +
+ +
+
Component Network Allocation
+ + + + +
+ +
+
System Component Health Checks
+ + + + + +
+ + + + + +
+ + + + +
+ +
+
Global Arguments & Configuration
+ + +
+
+ +
+
+

Active Actor Templates

+
+
+ + + + + + + + + {{ range .Templates }} + + + + + {{ else }} + + + + {{ end }} + +
NameNamespace
{{ .Name }}{{ .Namespace }}
No ActorTemplates are currently being handled.
+
+
+ +
+
+

Recent 100 Processing Inquiries Served

+ +
+ +
+ + + + + + + + + + + + + + {{ range .Queries }} + + + + + + + + + + {{ else }} + + + + {{ end }} + +
TimestampClient / AuthorityPath / RouteMethodMatching Action ResultSelected Target IPLatency
{{ .Timestamp }}{{ .Client }}{{ .Path }}{{ .Method }}{{ .Action }}{{ .Target }}{{ .Duration }}
No queries have been processed yet.
+
+
+
+ + + + diff --git a/cmd/servers/atenet/app/router/envoyrunner.go b/cmd/servers/atenet/app/router/envoyrunner.go new file mode 100644 index 000000000..8d38be29f --- /dev/null +++ b/cmd/servers/atenet/app/router/envoyrunner.go @@ -0,0 +1,258 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "fmt" + "log/slog" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + EnvoyDeploymentName = "atenet-router-envoy" + EnvoyServiceName = "atenet-router-envoy" + EnvoyConfigMapName = "atenet-router-envoy-config" +) + +// envoyrunner manages the dynamic deployment and lifecycle of the underlying +// Envoy proxy instance running inside Kubernetes. +type envoyrunner struct { + k8sClient client.Client + cfg RouterConfig +} + +func newEnvoyRunner(k8sClient client.Client, cfg RouterConfig) *envoyrunner { + return &envoyrunner{ + k8sClient: k8sClient, + cfg: cfg, + } +} + +func (r *envoyrunner) reconcile(ctx context.Context) error { + if err := r.reconcileEnvoyConfigMap(ctx); err != nil { + return fmt.Errorf("failed configmap reconciliation: %w", err) + } + + if err := r.reconcileEnvoyDeployment(ctx); err != nil { + return fmt.Errorf("failed deployment reconciliation: %w", err) + } + + if err := r.reconcileEnvoyService(ctx); err != nil { + return fmt.Errorf("failed service reconciliation: %w", err) + } + + return nil +} + +func (r *envoyrunner) reconcileEnvoyConfigMap(ctx context.Context) error { + envoyYaml := fmt.Sprintf(`admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9901 + +node: + id: %s + cluster: substrate-router-cluster + +dynamic_resources: + lds_config: + resource_api_version: V3 + ads: {} + cds_config: + resource_api_version: V3 + ads: {} + ads_config: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + +static_resources: + clusters: + - name: xds_cluster + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: atenet-router + port_value: %d +`, NodeID, r.cfg.XdsPort) + + cm := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: EnvoyConfigMapName, + Namespace: r.cfg.Namespace, + }, + Data: map[string]string{ + "envoy.yaml": envoyYaml, + }, + } + + var existing corev1.ConfigMap + err := r.k8sClient.Get(ctx, client.ObjectKey{Namespace: r.cfg.Namespace, Name: EnvoyConfigMapName}, &existing) + if err != nil { + if k8serrors.IsNotFound(err) { + slog.InfoContext(ctx, "Creating Envoy bootstrap ConfigMap", + slog.String("namespace", r.cfg.Namespace), + slog.String("name", EnvoyConfigMapName)) + return r.k8sClient.Create(ctx, cm) + } + return err + } + + existing.Data = cm.Data + return r.k8sClient.Update(ctx, &existing) +} + +func (r *envoyrunner) reconcileEnvoyDeployment(ctx context.Context) error { + replicas := int32(1) + + dep := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: EnvoyDeploymentName, + Namespace: r.cfg.Namespace, + Labels: map[string]string{ + "app": "atenet-router-envoy", + }, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "atenet-router-envoy", + }, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "app": "atenet-router-envoy", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "envoy", + Image: r.cfg.EnvoyImage, + Command: []string{ + "/usr/local/bin/envoy", + "-c", + "/etc/envoy/envoy.yaml", + "--component-log-level", + "upstream:debug,router:debug,ext_proc:debug", + }, + Ports: []corev1.ContainerPort{ + { + Name: "http", + ContainerPort: int32(r.cfg.HttpPort), + }, + { + Name: "admin", + ContainerPort: 9901, + }, + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "envoy-config", + MountPath: "/etc/envoy", + }, + }, + }, + }, + Volumes: []corev1.Volume{ + { + Name: "envoy-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: EnvoyConfigMapName, + }, + }, + }, + }, + }, + }, + }, + }, + } + + var existing appsv1.Deployment + err := r.k8sClient.Get(ctx, client.ObjectKey{Namespace: r.cfg.Namespace, Name: EnvoyDeploymentName}, &existing) + if err != nil { + if k8serrors.IsNotFound(err) { + slog.InfoContext(ctx, "Creating managed Envoy router Deployment", slog.String("namespace", r.cfg.Namespace)) + return r.k8sClient.Create(ctx, dep) + } + return err + } + + existing.Spec = dep.Spec + return r.k8sClient.Update(ctx, &existing) +} + +func (r *envoyrunner) reconcileEnvoyService(ctx context.Context) error { + svc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: EnvoyServiceName, + Namespace: r.cfg.Namespace, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeClusterIP, + Selector: map[string]string{ + "app": "atenet-router-envoy", + }, + Ports: []corev1.ServicePort{ + { + Name: "http", + Port: int32(r.cfg.HttpPort), + TargetPort: intstr.FromString("http"), + }, + }, + }, + } + + var existing corev1.Service + err := r.k8sClient.Get(ctx, client.ObjectKey{Namespace: r.cfg.Namespace, Name: EnvoyServiceName}, &existing) + if err != nil { + if k8serrors.IsNotFound(err) { + slog.InfoContext(ctx, "Creating managed Envoy router ClusterIP service", slog.String("namespace", r.cfg.Namespace)) + return r.k8sClient.Create(ctx, svc) + } + return err + } + + existing.Spec.Ports = svc.Spec.Ports + existing.Spec.Selector = svc.Spec.Selector + return r.k8sClient.Update(ctx, &existing) +} diff --git a/cmd/servers/atenet/app/router/extproc.go b/cmd/servers/atenet/app/router/extproc.go new file mode 100644 index 000000000..834728f8e --- /dev/null +++ b/cmd/servers/atenet/app/router/extproc.go @@ -0,0 +1,162 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "errors" + "fmt" + "io" + "log/slog" + "net" + "time" + + extprocv3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" + envoy_type "github.com/envoyproxy/go-control-plane/envoy/type/v3" + "google.golang.org/grpc" + + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +// ExtProcServer implements the Envoy external processing gRPC server +// to dynamically manage actor activations based on request traffic. +type ExtProcServer struct { + port int + apiClient ateapipb.ControlClient + recorder *QueryRecorder + resumer *ActorResumer +} + +func NewExtProcServer(port int, apiClient ateapipb.ControlClient) *ExtProcServer { + return &ExtProcServer{ + port: port, + apiClient: apiClient, + recorder: NewQueryRecorder(100), + resumer: NewActorResumer(apiClient), + } +} + +func (s *ExtProcServer) Serve(ctx context.Context, lis net.Listener) error { + grpcServer := grpc.NewServer() + extprocv3.RegisterExternalProcessorServer(grpcServer, s) + + errChan := make(chan error, 1) + go func() { + if err := grpcServer.Serve(lis); err != nil { + errChan <- err + } + }() + + select { + case <-ctx.Done(): + grpcServer.GracefulStop() + return nil + case err := <-errChan: + return err + } +} + +func (s *ExtProcServer) Process(stream extprocv3.ExternalProcessor_ProcessServer) error { + for { + req, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + + resp := &extprocv3.ProcessingResponse{} + + switch reqType := req.Request.(type) { + case *extprocv3.ProcessingRequest_RequestHeaders: + start := time.Now() + hResponse, rqm, err := s.handleRequestHeaders(stream.Context(), reqType.RequestHeaders) + if err != nil { + slog.ErrorContext(stream.Context(), "Error during ext_proc RequestHeaders processing", slog.String("err", err.Error())) + var reqErr *reqError + if errors.As(err, &reqErr) { + resp = immediateResponse(envoy_type.StatusCode(reqErr.statusCode), reqErr.Error()) + } else { + resp = immediateResponse(envoy_type.StatusCode_InternalServerError, err.Error()) + } + s.recorder.AddRouterRequest(start, time.Since(start), "Error", "-", rqm) + } else { + resp.Response = &extprocv3.ProcessingResponse_RequestHeaders{RequestHeaders: hResponse} + s.recorder.AddRouterRequest(start, time.Since(start), "Route ok", "-", rqm) + } + + default: + // No modification for other processing states, but log because this should + // not be called. + slog.Error("Unexpected request type", slog.Any("reqType", reqType)) + resp.Response = &extprocv3.ProcessingResponse_RequestHeaders{ + RequestHeaders: &extprocv3.HeadersResponse{ + Response: &extprocv3.CommonResponse{}, + }, + } + } + + if err := stream.Send(resp); err != nil { + return err + } + } +} + +func (s *ExtProcServer) handleRequestHeaders( + ctx context.Context, + reqHeaders *extprocv3.HttpHeaders, +) (*extprocv3.HeadersResponse, *requestMetadata, error) { + metadata := newRequestMetadata(reqHeaders.Headers.GetHeaders()) + slog.InfoContext(ctx, "Request", slog.String("metadata", metadata.String())) + + actorID, err := parseActorID(metadata.host) + if err != nil { + // Host is invalid, respond with 404. + return nil, metadata, notFoundErr + } + + slog.InfoContext(ctx, "ResumeActor", slog.String("actorID", actorID)) + actor, err := s.resumer.ResumeActor(ctx, actorID) + + slog.InfoContext(ctx, "ResumeActor result", + slog.String("actor", fmt.Sprintf("%+v", actor)), + slog.String("worker_ip", actor.GetAteomPodIp()), + slog.Any("err", err)) + + if err != nil { + return nil, metadata, fmt.Errorf("error resuming actor %s: %w", actorID, err) + } + + workerIP := actor.GetAteomPodIp() + if ip := net.ParseIP(workerIP); ip == nil { + return nil, metadata, fmt.Errorf("actor %q did not have a valid IP %q", actorID, workerIP) + } + + // TODO(bowei) -- handle more than port 80 on the actor. + targetAddr := net.JoinHostPort(workerIP, "80") + + slog.InfoContext(ctx, "Route ok", slog.String("actorID", actorID), slog.String("targetAddr", targetAddr)) + + // Route by rewriting the :authority header. + mutation := &extprocv3.HeaderMutation{} + addAuthorityMutation(targetAddr, mutation) + + return &extprocv3.HeadersResponse{ + Response: &extprocv3.CommonResponse{ + HeaderMutation: mutation, + }, + }, metadata, nil +} diff --git a/cmd/servers/atenet/app/router/extproc_in.go b/cmd/servers/atenet/app/router/extproc_in.go new file mode 100644 index 000000000..317511845 --- /dev/null +++ b/cmd/servers/atenet/app/router/extproc_in.go @@ -0,0 +1,81 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "fmt" + "net" + "strings" + + "github.com/agent-substrate/substrate/internal/resources" + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" +) + +type requestMetadata struct { + headers map[string]string + path string + host string +} + +func (m *requestMetadata) String() string { + return fmt.Sprintf("%+v", *m) +} + +func newRequestMetadata(headers []*corev3.HeaderValue) *requestMetadata { + headersMap := make(map[string]string) + var path string + var host string + + for _, h := range headers { + k := strings.ToLower(h.Key) + val := h.Value + if val == "" && len(h.RawValue) > 0 { + val = string(h.RawValue) + } + + headersMap[k] = val + if k == ":path" { + path = val + } + if k == ":authority" || k == "host" { + host = val + } + } + + return &requestMetadata{ + headers: headersMap, + path: path, + host: host, + } +} + +func parseActorID(host string) (string, error) { + var err error + if strings.Contains(host, ":") { + host, _, err = net.SplitHostPort(host) + } + if err != nil { + return "", err + } + actorID, found := strings.CutSuffix(strings.TrimSuffix(host, "."), "."+resources.ActorDNSSuffix) + if !found { + return "", fmt.Errorf("invalid actor_id: must end with %s, got %q", resources.ActorDNSSuffix, host) + } + if err := resources.ValidateActorID(actorID); err != nil { + return "", err + } + + return actorID, nil +} diff --git a/cmd/servers/atenet/app/router/extproc_in_test.go b/cmd/servers/atenet/app/router/extproc_in_test.go new file mode 100644 index 000000000..09bb9a4c4 --- /dev/null +++ b/cmd/servers/atenet/app/router/extproc_in_test.go @@ -0,0 +1,195 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "fmt" + "reflect" + "testing" + + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" +) + +func TestExtractMetadata(t *testing.T) { + tests := []struct { + name string + headers []*corev3.HeaderValue + wantHeaders map[string]string + wantPath string + wantHost string + }{ + { + name: "basic path and authority", + headers: []*corev3.HeaderValue{ + {Key: ":path", Value: "/api/v1/test"}, + {Key: ":authority", Value: "example.com"}, + {Key: "X-Request-ID", Value: "req-123"}, + }, + wantHeaders: map[string]string{ + ":path": "/api/v1/test", + ":authority": "example.com", + "x-request-id": "req-123", + }, + wantPath: "/api/v1/test", + wantHost: "example.com", + }, + { + name: "host header overrides empty or authority", + headers: []*corev3.HeaderValue{ + {Key: ":path", Value: "/api/v1/test"}, + {Key: ":authority", Value: "authority.com"}, + {Key: "Host", Value: "host.com"}, + }, + wantHeaders: map[string]string{ + ":path": "/api/v1/test", + ":authority": "authority.com", + "host": "host.com", + }, + wantPath: "/api/v1/test", + wantHost: "host.com", + }, + { + name: "authority header overrides host when it comes after", + headers: []*corev3.HeaderValue{ + {Key: ":path", Value: "/api/v1/test"}, + {Key: "Host", Value: "host.com"}, + {Key: ":authority", Value: "authority.com"}, + }, + wantHeaders: map[string]string{ + ":path": "/api/v1/test", + "host": "host.com", + ":authority": "authority.com", + }, + wantPath: "/api/v1/test", + wantHost: "authority.com", + }, + { + name: "no authority or host headers", + headers: []*corev3.HeaderValue{ + {Key: ":path", Value: "/api/v1/test"}, + {Key: "x-something-else", Value: "custom-value"}, + }, + wantHeaders: map[string]string{ + ":path": "/api/v1/test", + "x-something-else": "custom-value", + }, + wantPath: "/api/v1/test", + wantHost: "", + }, + { + name: "headers are lowercased", + headers: []*corev3.HeaderValue{ + {Key: "UPPER-KEY", Value: "UPPER-VALUE"}, + {Key: "camelCaseKey", Value: "camelValue"}, + }, + wantHeaders: map[string]string{ + "upper-key": "UPPER-VALUE", + "camelcasekey": "camelValue", + }, + wantPath: "", + wantHost: "", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := newRequestMetadata(tc.headers) + + if !reflect.DeepEqual(got.headers, tc.wantHeaders) { + t.Errorf("extractMetadata() headersMap = %v, want %v", got.headers, tc.wantHeaders) + } + if got.path != tc.wantPath { + t.Errorf("extractMetadata() path = %v, want %v", got.path, tc.wantPath) + } + if got.host != tc.wantHost { + t.Errorf("extractMetadata() host = %v, want %v", got.host, tc.wantHost) + } + }) + } +} + +func TestRequestMetadata_String(t *testing.T) { + headers := []*corev3.HeaderValue{ + {Key: ":path", Value: "/api/v1/test"}, + {Key: ":authority", Value: "example.com"}, + } + m := newRequestMetadata(headers) + str := m.String() + if str == "" { + t.Errorf("expected non-empty string from String()") + } + if !reflect.DeepEqual(str, fmt.Sprintf("%+v", *m)) { + t.Errorf("String() = %q, want %q", str, fmt.Sprintf("%+v", *m)) + } +} + +func TestParseActorID(t *testing.T) { + tests := []struct { + name string + host string + wantID string + wantErr bool + }{ + { + name: "valid host without port", + host: "my-actor.actors.resources.substrate.ate.dev", + wantID: "my-actor", + wantErr: false, + }, + { + name: "valid host with port", + host: "my-actor.actors.resources.substrate.ate.dev:8443", + wantID: "my-actor", + wantErr: false, + }, + { + name: "valid host with trailing dot", + host: "my-actor.actors.resources.substrate.ate.dev.", + wantID: "my-actor", + wantErr: false, + }, + { + name: "valid host with trailing dot and port", + host: "my-actor.actors.resources.substrate.ate.dev.:8080", + wantID: "my-actor", + wantErr: false, + }, + { + name: "invalid suffix", + host: "my-actor.example.com", + wantID: "", + wantErr: true, + }, + { + name: "invalid host port format", + host: "my-actor.actors.resources.substrate.ate.dev:invalid:port", + wantID: "", + wantErr: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + gotID, err := parseActorID(tc.host) + if (err != nil) != tc.wantErr { + t.Errorf("parseActorID(%q) error = %v, wantErr %v", tc.host, err, tc.wantErr) + return + } + if gotID != tc.wantID { + t.Errorf("parseActorID(%q) gotID = %v, want %v", tc.host, gotID, tc.wantID) + } + }) + } +} diff --git a/cmd/servers/atenet/app/router/extproc_out.go b/cmd/servers/atenet/app/router/extproc_out.go new file mode 100644 index 000000000..c7386c554 --- /dev/null +++ b/cmd/servers/atenet/app/router/extproc_out.go @@ -0,0 +1,67 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "errors" + + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + extproc "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" + extprocv3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" + envoy_type "github.com/envoyproxy/go-control-plane/envoy/type/v3" +) + +type reqError struct { + error + statusCode int +} + +var ( + notFoundErr = &reqError{error: errors.New("not found"), statusCode: int(envoy_type.StatusCode_NotFound)} +) + +func addAuthorityMutation(auth string, mut *extprocv3.HeaderMutation) { + mut.SetHeaders = append(mut.SetHeaders, + &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: ":authority", + RawValue: []byte(auth), + }, + }, + ) +} + +func immediateResponse(statusCode envoy_type.StatusCode, message string) *extproc.ProcessingResponse { + return &extproc.ProcessingResponse{ + Response: &extproc.ProcessingResponse_ImmediateResponse{ + ImmediateResponse: &extproc.ImmediateResponse{ + Status: &envoy_type.HttpStatus{ + Code: statusCode, + }, + Body: []byte(message), + Headers: &extproc.HeaderMutation{ + SetHeaders: []*corev3.HeaderValueOption{ + { + Header: &corev3.HeaderValue{ + Key: "content-type", + Value: "text/plain", + }, + }, + }, + }, + }, + }, + } +} diff --git a/cmd/servers/atenet/app/router/extproc_test.go b/cmd/servers/atenet/app/router/extproc_test.go new file mode 100644 index 000000000..d948184eb --- /dev/null +++ b/cmd/servers/atenet/app/router/extproc_test.go @@ -0,0 +1,155 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "errors" + "strings" + "testing" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + extprocv3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" + "google.golang.org/grpc" +) + +type mockClient struct { + ateapipb.ControlClient + resumeFn func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) +} + +func (m *mockClient) ResumeActor(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + return m.resumeFn(ctx, in, opts...) +} + +func TestExtProcHeadersEvaluation(t *testing.T) { + const testUUID = "123e4567-e89b-12d3-a456-426614174000" + + tests := []struct { + name string + authority string + resumeResp *ateapipb.ResumeActorResponse + resumeErr error + expectErr bool + expectedErr error + expectedErrStr string + expectedTarget string + }{ + { + name: "invalid host", + authority: "invalid-host.com", + expectErr: true, + expectedErr: notFoundErr, + }, + { + name: "Error resuming actor", + authority: testUUID + ".actors.resources.substrate.ate.dev", + resumeErr: errors.New("resume failed"), + expectErr: true, + expectedErrStr: "error resuming actor 123e4567-e89b-12d3-a456-426614174000: resume failed", + }, + { + name: "Bad Actor IP from resume", + authority: testUUID + ".actors.resources.substrate.ate.dev", + resumeResp: &ateapipb.ResumeActorResponse{ + Actor: &ateapipb.Actor{ + AteomPodIp: "invalid-ip", + }, + }, + expectErr: true, + expectedErrStr: "actor \"123e4567-e89b-12d3-a456-426614174000\" did not have a valid IP \"invalid-ip\"", + }, + { + name: "Successful resume", + authority: testUUID + ".actors.resources.substrate.ate.dev", + resumeResp: &ateapipb.ResumeActorResponse{ + Actor: &ateapipb.Actor{ + AteomPodIp: "10.0.0.52", + }, + }, + expectErr: false, + expectedTarget: "10.0.0.52:80", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + clientMock := &mockClient{ + resumeFn: func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + if in.GetActorId() != testUUID { + t.Errorf("unexpected identifier parsed in test context: %s", in.GetActorId()) + } + if tc.resumeErr != nil { + return nil, tc.resumeErr + } + return tc.resumeResp, nil + }, + } + + s := NewExtProcServer(50051, clientMock) + + reqHeaders := &extprocv3.HttpHeaders{ + Headers: &corev3.HeaderMap{ + Headers: []*corev3.HeaderValue{ + {Key: ":path", Value: "/v1/actors/invoke"}, + {Key: ":authority", Value: tc.authority}, + {Key: ":method", Value: "POST"}, + }, + }, + } + + res, metadata, err := s.handleRequestHeaders(context.Background(), reqHeaders) + if tc.expectErr { + if err == nil { + t.Fatalf("expected error but got nil") + } + if tc.expectedErr != nil && !errors.Is(err, tc.expectedErr) { + t.Errorf("expected error %v, got %v", tc.expectedErr, err) + } + if tc.expectedErrStr != "" && err.Error() != tc.expectedErrStr { + t.Errorf("expected error string %q, got %q", tc.expectedErrStr, err.Error()) + } + return + } + + if err != nil { + t.Fatalf("ext_proc processing error: %v", err) + } + + mutation := res.Response.GetHeaderMutation() + if len(mutation.GetSetHeaders()) != 1 { + t.Fatalf("expected exactly one Header option set, found: %v", mutation.GetSetHeaders()) + } + + headerOption := mutation.GetSetHeaders()[0] + if strings.ToLower(headerOption.Header.Key) != ":authority" { + t.Errorf("invalid resulting dynamic parameter key: %s", headerOption.Header.Key) + } + + if string(headerOption.Header.RawValue) != tc.expectedTarget { + t.Errorf("invalid destination mapping found: %s, expected: %s", headerOption.Header.RawValue, tc.expectedTarget) + } + + // Confirm that query logs recorded metric trace details + s.recorder.AddRouterRequest(time.Now(), 10*time.Millisecond, "Route ok", tc.expectedTarget, metadata) + queries := s.recorder.Get() + if len(queries) != 1 { + t.Errorf("expected query trace entries, got: %v", queries) + } + }) + } +} diff --git a/cmd/servers/atenet/app/router/health.go b/cmd/servers/atenet/app/router/health.go new file mode 100644 index 000000000..9f2358f63 --- /dev/null +++ b/cmd/servers/atenet/app/router/health.go @@ -0,0 +1,214 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "fmt" + "io" + "log/slog" + "net/http" + "strings" + "sync" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "k8s.io/client-go/kubernetes" +) + +type ComponentHealth struct { + Healthy bool `json:"healthy"` + Message string `json:"message,omitempty"` + LastSuccess time.Time `json:"last_success,omitempty"` + LastFailure time.Time `json:"last_failure,omitempty"` + SuccessCount int64 `json:"success_count"` + FailureCount int64 `json:"failure_count"` +} + +type RouterHealthReport struct { + Envoy ComponentHealth `json:"envoy"` + K8sAPI ComponentHealth `json:"k8s_api"` + AteAPI ComponentHealth `json:"ate_api"` +} + +// routerHealth periodically checks the dependent services of router to track health +// status of this component. +type routerHealth struct { + mu sync.RWMutex + + report RouterHealthReport + + interval time.Duration + clientset kubernetes.Interface + apiClient ateapipb.ControlClient + cfg RouterConfig +} + +func newRouterHealth(interval time.Duration, clientset kubernetes.Interface, apiClient ateapipb.ControlClient, cfg RouterConfig) *routerHealth { + if interval <= 0 { + interval = time.Second + } + return &routerHealth{ + interval: interval, + clientset: clientset, + apiClient: apiClient, + cfg: cfg, + } +} + +func (rh *routerHealth) Start(ctx context.Context) { + ticker := time.NewTicker(rh.interval) + defer ticker.Stop() + + // Trigger immediate check + rh.check(ctx) + + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + rh.check(ctx) + } + } +} + +func (rh *routerHealth) check(ctx context.Context) { + rh.mu.Lock() + defer rh.mu.Unlock() + + slog.InfoContext(ctx, "Checking health") + + // 1. Check Envoy + { + healthy, msg := rh.checkEnvoy(ctx) + if healthy { + rh.report.Envoy.Healthy = true + rh.report.Envoy.Message = msg + rh.report.Envoy.LastSuccess = time.Now() + rh.report.Envoy.SuccessCount++ + } else { + rh.report.Envoy.Healthy = false + rh.report.Envoy.Message = msg + rh.report.Envoy.LastFailure = time.Now() + rh.report.Envoy.FailureCount++ + slog.ErrorContext(ctx, "Envoy health check failed", slog.String("msg", msg)) + } + } + + // 2. Check Kubernetes API + { + healthy, msg := rh.checkK8s() + if healthy { + rh.report.K8sAPI.Healthy = true + rh.report.K8sAPI.Message = msg + rh.report.K8sAPI.LastSuccess = time.Now() + rh.report.K8sAPI.SuccessCount++ + } else { + rh.report.K8sAPI.Healthy = false + rh.report.K8sAPI.Message = msg + rh.report.K8sAPI.LastFailure = time.Now() + rh.report.K8sAPI.FailureCount++ + slog.ErrorContext(ctx, "Kubernetes API health check failed", slog.String("msg", msg)) + } + } + + // 3. Check ATE API gRPC + { + healthy, msg := rh.checkAteAPI(ctx) + if healthy { + rh.report.AteAPI.Healthy = true + rh.report.AteAPI.Message = msg + rh.report.AteAPI.LastSuccess = time.Now() + rh.report.AteAPI.SuccessCount++ + } else { + rh.report.AteAPI.Healthy = false + rh.report.AteAPI.Message = msg + rh.report.AteAPI.LastFailure = time.Now() + rh.report.AteAPI.FailureCount++ + slog.ErrorContext(ctx, "ATE API gRPC health check failed", slog.String("msg", msg)) + } + } +} + +func (rh *routerHealth) checkEnvoy(ctx context.Context) (bool, string) { + timeoutCtx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) + defer cancel() + + req, err := http.NewRequestWithContext(timeoutCtx, "GET", "http://127.0.0.1:9901/ready", nil) + if err != nil { + return false, err.Error() + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false, err.Error() + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return false, fmt.Sprintf("unexpected status code %d", resp.StatusCode) + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return false, err.Error() + } + + bodyStr := strings.TrimSpace(string(bodyBytes)) + if bodyStr != "LIVE" { + return false, fmt.Sprintf("expected LIVE but got %q", bodyStr) + } + + return true, "LIVE" +} + +func (rh *routerHealth) checkK8s() (bool, string) { + if rh.clientset == nil { + return true, "Skipped (standalone/file store)" + } + + ver, err := rh.clientset.Discovery().ServerVersion() + if err != nil { + return false, err.Error() + } + + return true, fmt.Sprintf("Version: %s", ver.GitVersion) +} + +func (rh *routerHealth) checkAteAPI(ctx context.Context) (bool, string) { + if rh.apiClient == nil { + return false, "No client" + } + + timeoutCtx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) + defer cancel() + + _, err := rh.apiClient.ListActors(timeoutCtx, &ateapipb.ListActorsRequest{}) + if err != nil { + return false, err.Error() + } + + return true, "Connected" +} + +func (rh *routerHealth) Report() RouterHealthReport { + if rh == nil { + return RouterHealthReport{} + } + rh.mu.RLock() + defer rh.mu.RUnlock() + return rh.report +} diff --git a/cmd/servers/atenet/app/router/readme.md b/cmd/servers/atenet/app/router/readme.md new file mode 100644 index 000000000..4f05ae839 --- /dev/null +++ b/cmd/servers/atenet/app/router/readme.md @@ -0,0 +1,26 @@ +# router + +Router has several responsibilities: + +* (Optional) manages a Deployment of Envoy to function as a router for ATE requests. + * This is optional to enable testing the router component in a standalone mode without managing the Kubernetes objects. + * Envoy will be configured to send traffic to via xDS served by the Router. +* ext_proc server for the Envoy. To make the deployment and debugging easier, we will run this component together + with the router, but this will be split later into its own component. + * ext_proc will call into the ATE gRPC API to get the set of relevant backends (specific the worker IP) and + route the traffic accordingly + * Make sure the interface with ATE API is pluggable so that we can test with a mock ATE API. +* Runs an xDS server for the Envoy deployment that defines the Cluster information for the ATEs. + * the xDS configuration will configure Envoy to send traffic to ext_proc +* Watches the ActorTemplates to get out the definitions for how to route the session IDs. + +## status page + +Serve a `/statusz` page on port 8080. + +Contents: + +* Global flags values +* Command line args +* Last 100 queries served +* Build tag \ No newline at end of file diff --git a/cmd/servers/atenet/app/router/resumer.go b/cmd/servers/atenet/app/router/resumer.go new file mode 100644 index 000000000..0ad3586ae --- /dev/null +++ b/cmd/servers/atenet/app/router/resumer.go @@ -0,0 +1,93 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "golang.org/x/sync/singleflight" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "k8s.io/apimachinery/pkg/util/wait" +) + +// ActorResumer coordinates safe, deduplicated resumption of actors. +type ActorResumer struct { + apiClient ateapipb.ControlClient + flight singleflight.Group +} + +func NewActorResumer(apiClient ateapipb.ControlClient) *ActorResumer { + return &ActorResumer{ + apiClient: apiClient, + } +} + +// ResumeActor ensures the requested actor is running. It deduplicates concurrent +// requests within the process and retries when needed. +func (r *ActorResumer) ResumeActor(ctx context.Context, actorID string) (*ateapipb.Actor, error) { + ch := r.flight.DoChan(actorID, func() (interface{}, error) { + // We detach the context from the first caller using a fixed background timeout. + // This guarantees that if Caller 1 disconnects or times out, the underlying + // resume operation continues running for Caller 2 and Caller 3 without failing. + bgCtx, bgCancel := context.WithTimeout(context.Background(), 15*time.Second) + defer bgCancel() + + backoff := wait.Backoff{ + Steps: 7, + Duration: 200 * time.Millisecond, + Factor: 1.5, + Jitter: 0.2, + } + + var resumeResp *ateapipb.ResumeActorResponse + + err := wait.ExponentialBackoffWithContext(bgCtx, backoff, func(ctx context.Context) (bool, error) { + var err error + resumeResp, err = r.apiClient.ResumeActor(ctx, &ateapipb.ResumeActorRequest{ + ActorId: actorID, + }) + if err == nil { + return true, nil + } + + if status.Code(err) == codes.Aborted { + return false, nil // Concurrent resume call, retry. + } + if status.Code(err) == codes.NotFound { + return false, notFoundErr + } + return false, err + }) + + if err != nil { + return nil, err + } + + return resumeResp.GetActor(), nil + }) + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case res := <-ch: + if res.Err != nil { + return nil, res.Err + } + return res.Val.(*ateapipb.Actor), nil + } +} diff --git a/cmd/servers/atenet/app/router/resumer_test.go b/cmd/servers/atenet/app/router/resumer_test.go new file mode 100644 index 000000000..6aab1ce9c --- /dev/null +++ b/cmd/servers/atenet/app/router/resumer_test.go @@ -0,0 +1,170 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "errors" + "sync" + "testing" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type resumerMockClient struct { + ateapipb.ControlClient + resumeFn func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) +} + +func (m *resumerMockClient) ResumeActor(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + if m.resumeFn != nil { + return m.resumeFn(ctx, in, opts...) + } + return nil, status.Error(codes.Unimplemented, "unimplemented") +} + +func TestActorResumer_ResumeActor(t *testing.T) { + const testActorID = "actor-a" + const expectedIP = "10.0.0.52" + + t.Run("SuspendedResumedSuccessfully", func(t *testing.T) { + var resumeCalled int + mock := &resumerMockClient{ + resumeFn: func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + resumeCalled++ + return &ateapipb.ResumeActorResponse{ + Actor: &ateapipb.Actor{ + ActorId: testActorID, + Status: ateapipb.Actor_STATUS_RUNNING, + AteomPodIp: expectedIP, + }, + }, nil + }, + } + + resumer := NewActorResumer(mock) + actor, err := resumer.ResumeActor(context.Background(), testActorID) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if actor.GetAteomPodIp() != expectedIP { + t.Errorf("expected IP %q, got %q", expectedIP, actor.GetAteomPodIp()) + } + if resumeCalled != 1 { + t.Errorf("expected ResumeActor called 1 time, got %d", resumeCalled) + } + }) + + t.Run("RetryOnAbortedConflict", func(t *testing.T) { + var resumeCalled int + mock := &resumerMockClient{ + resumeFn: func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + resumeCalled++ + if resumeCalled < 3 { + return nil, status.Error(codes.Aborted, "concurrent update conflict") + } + return &ateapipb.ResumeActorResponse{ + Actor: &ateapipb.Actor{ + ActorId: testActorID, + Status: ateapipb.Actor_STATUS_RUNNING, + AteomPodIp: expectedIP, + }, + }, nil + }, + } + + resumer := NewActorResumer(mock) + actor, err := resumer.ResumeActor(context.Background(), testActorID) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if actor.GetAteomPodIp() != expectedIP { + t.Errorf("expected IP %q, got %q", expectedIP, actor.GetAteomPodIp()) + } + if resumeCalled != 3 { + t.Errorf("expected ResumeActor called 3 times, got %d", resumeCalled) + } + }) + + t.Run("ActorNotFound", func(t *testing.T) { + mock := &resumerMockClient{ + resumeFn: func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + return nil, status.Error(codes.NotFound, "not found") + }, + } + + resumer := NewActorResumer(mock) + _, err := resumer.ResumeActor(context.Background(), testActorID) + if !errors.Is(err, notFoundErr) { + t.Errorf("expected notFoundErr, got %v", err) + } + }) + + t.Run("SingleflightDeduplication", func(t *testing.T) { + var resumeCalled int + var mu sync.Mutex + + mock := &resumerMockClient{ + resumeFn: func(ctx context.Context, in *ateapipb.ResumeActorRequest, opts ...grpc.CallOption) (*ateapipb.ResumeActorResponse, error) { + mu.Lock() + resumeCalled++ + mu.Unlock() + time.Sleep(20 * time.Millisecond) + return &ateapipb.ResumeActorResponse{ + Actor: &ateapipb.Actor{ + ActorId: testActorID, + Status: ateapipb.Actor_STATUS_RUNNING, + AteomPodIp: expectedIP, + }, + }, nil + }, + } + + resumer := NewActorResumer(mock) + + var wg sync.WaitGroup + const concurrentRequests = 10 + results := make([]*ateapipb.Actor, concurrentRequests) + errs := make([]error, concurrentRequests) + + wg.Add(concurrentRequests) + for i := 0; i < concurrentRequests; i++ { + go func(idx int) { + defer wg.Done() + results[idx], errs[idx] = resumer.ResumeActor(context.Background(), testActorID) + }(i) + } + wg.Wait() + + for i := 0; i < concurrentRequests; i++ { + if errs[i] != nil { + t.Fatalf("request %d failed: %v", i, errs[i]) + } + if results[i].GetAteomPodIp() != expectedIP { + t.Errorf("request %d expected IP %q, got %q", i, expectedIP, results[i].GetAteomPodIp()) + } + } + + mu.Lock() + defer mu.Unlock() + if resumeCalled != 1 { + t.Errorf("expected ResumeActor called exactly once by singleflight, got %d", resumeCalled) + } + }) +} diff --git a/cmd/servers/atenet/app/router/router.go b/cmd/servers/atenet/app/router/router.go new file mode 100644 index 000000000..884c31114 --- /dev/null +++ b/cmd/servers/atenet/app/router/router.go @@ -0,0 +1,334 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "log/slog" + "math/big" + "net" + "net/http" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + + v1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +var ( + scheme = runtime.NewScheme() +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(v1alpha1.AddToScheme(scheme)) +} + +// RouterConfig holds deployment setup and endpoint options for the router node instance. +type RouterConfig struct { + Standalone bool + Namespace string + Kubeconfig string + AteapiAddr string + HttpPort int + XdsPort int + ExtprocPort int + ExtprocAddr string + EnvoyImage string + TemplatesFile string + StatusPort int + HealthInterval time.Duration + HttpsPort int + EnvoyCertPath string + LogLevel string +} + +// RouterServer instantiates and coordinates runtime threads executing system modules. +type RouterServer struct { + cfg RouterConfig + + cmd *cobra.Command + k8sClient client.Client + clientset kubernetes.Interface + apiClient ateapipb.ControlClient + extprocSrv *ExtProcServer + health *routerHealth + atStore atStore +} + +func NewCmd() *cobra.Command { + var cfg RouterConfig + + cmd := &cobra.Command{ + Use: "router", + Short: "Router components including xDS server and Envoy ExtProc gateway processing server", + RunE: func(cmd *cobra.Command, args []string) error { + ctx, cancel := context.WithCancel(cmd.Context()) + defer cancel() + + var level slog.Level + switch strings.ToLower(cfg.LogLevel) { + case "debug": + level = slog.LevelDebug + case "warn": + level = slog.LevelWarn + case "error": + level = slog.LevelError + default: + level = slog.LevelInfo + } + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: level}))) + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + go func() { + <-sigChan + cancel() + }() + + srv, err := NewRouterServer(cfg) + if err != nil { + return fmt.Errorf("failed to create router server: %w", err) + } + srv.cmd = cmd + + return srv.Run(ctx) + }, + } + + cmd.Flags().StringVar(&cfg.LogLevel, "log-level", "info", "Log level: debug, info, warn, error") + cmd.Flags().BoolVar(&cfg.Standalone, "standalone", false, "Run in standalone mode, bypassing creation of managed deployment and services in Kubernetes cluster") + cmd.Flags().StringVar(&cfg.Namespace, "namespace", "default", "Target operations namespace") + cmd.Flags().StringVar(&cfg.Kubeconfig, "kubeconfig", "", "Absolute path to the kubeconfig configuration file") + cmd.Flags().StringVar(&cfg.AteapiAddr, "ateapi-address", "api.ate-system.svc:443", "gRPC host address of the cluster ateapi Control instance") + cmd.Flags().IntVar(&cfg.HttpPort, "port-http", 8080, "TCP port for workload traffic entering through the Envoy Router") + cmd.Flags().IntVar(&cfg.XdsPort, "port-xds", 18000, "TCP port listening for the xDS dynamic Envoy connections") + cmd.Flags().IntVar(&cfg.ExtprocPort, "port-extproc", 50051, "Listen port for the Envoy dynamic External Processing (ext_proc) server") + cmd.Flags().StringVar(&cfg.ExtprocAddr, "extproc-address", "127.0.0.1", "Host IP or address of the Envoy External Processing (ext_proc) server") + cmd.Flags().StringVar(&cfg.EnvoyImage, "envoy-image", "envoyproxy/envoy:v1.30-latest", "Image URI used for dynamically launched router instances") + cmd.Flags().StringVar(&cfg.TemplatesFile, "actor-templates-file", "", "Path to offline YAML configuration file listing ActorTemplates") + cmd.Flags().IntVar(&cfg.StatusPort, "status-port", 4040, "Port to serve /statusz on (set <= 0 to disable serving status)") + cmd.Flags().DurationVar(&cfg.HealthInterval, "health-interval", 1*time.Second, "Interval for checking health of dependent services") + cmd.Flags().IntVar(&cfg.HttpsPort, "port-https", 8443, "TCP port for HTTPS workload traffic entering through the Envoy Router") + cmd.Flags().StringVar(&cfg.EnvoyCertPath, "envoy-cert-path", "", "Path to the Envoy certificate file (if empty, a self-signed cert will be generated for testing)") + + return cmd +} + +func NewRouterServer(cfg RouterConfig) (*RouterServer, error) { + var k8sClient client.Client + var clientset kubernetes.Interface + var err error + + if cfg.TemplatesFile == "" { + k8sCfg, err := config.GetConfig() + if err != nil { + if cfg.Kubeconfig != "" { + k8sCfg, err = clientcmd.BuildConfigFromFlags("", cfg.Kubeconfig) + if err != nil { + return nil, fmt.Errorf("failed to read config from path %s: %w", cfg.Kubeconfig, err) + } + } else { + return nil, fmt.Errorf("unable to establish Kubernetes configuration parameters: %w", err) + } + } + slog.Info("Connecting to Kubernetes API server", slog.String("host", k8sCfg.Host)) + + k8sClient, err = client.New(k8sCfg, client.Options{ + Scheme: scheme, + }) + if err != nil { + return nil, fmt.Errorf("failed to initialize cluster client: %w", err) + } + + clientset, err = kubernetes.NewForConfig(k8sCfg) + if err != nil { + return nil, fmt.Errorf("failed to initialize core client: %w", err) + } + } + + conn, err := grpc.NewClient(cfg.AteapiAddr, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}))) + if err != nil { + return nil, fmt.Errorf("failed to establish grpc channel to ateapi client: %w", err) + } + slog.Info("Connecting to ateapi", slog.String("address", cfg.AteapiAddr)) + + apiClient := ateapipb.NewControlClient(conn) + + var store atStore + if cfg.TemplatesFile != "" { + store = newFileATStore(cfg.TemplatesFile) + } else { + store = newk8sATStore(k8sClient) + } + + return &RouterServer{ + cfg: cfg, + k8sClient: k8sClient, + clientset: clientset, + apiClient: apiClient, + atStore: store, + }, nil +} + +func (s *RouterServer) Run(ctx context.Context) error { + slog.InfoContext(ctx, "Starting substrate router subsystem", slog.Bool("standalone", s.cfg.Standalone)) + + g, ctx := errgroup.WithContext(ctx) + + xdsSrv := NewXdsServer(s.cfg.XdsPort) + xdsSrv.SetConfig(s.cfg.HttpPort, s.cfg.ExtprocPort, s.cfg.ExtprocAddr) + + var certContent, keyContent string + if s.cfg.EnvoyCertPath == "" { + slog.InfoContext(ctx, "No Envoy certificate path provided, generating self-signed certificate for testing") + var err error + certContent, keyContent, err = generateSelfSignedCert() + if err != nil { + return fmt.Errorf("failed to generate self-signed cert: %w", err) + } + } + + xdsSrv.SetTlsConfig(s.cfg.HttpsPort, s.cfg.EnvoyCertPath, certContent, keyContent) + if s.extprocSrv == nil { + s.extprocSrv = NewExtProcServer(s.cfg.ExtprocPort, s.apiClient) + } + ctrl := NewController(s.k8sClient, s.clientset, s.cfg, xdsSrv, s.extprocSrv) + + s.health = newRouterHealth(s.cfg.HealthInterval, s.clientset, s.apiClient, s.cfg) + + // Start Controller / Watcher + g.Go(func() error { + slog.InfoContext(ctx, "Starting ActorTemplate controller") + return ctrl.Start(ctx) + }) + + // Start periodic service checking logic + g.Go(func() error { + slog.InfoContext(ctx, "Starting periodic health checker", slog.Duration("interval", s.cfg.HealthInterval)) + s.health.Start(ctx) + return nil + }) + + // Start xDS Server + g.Go(func() error { + slog.InfoContext(ctx, "Starting Envoy xDS Server", slog.Int("port", s.cfg.XdsPort)) + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", s.cfg.XdsPort)) + if err != nil { + return fmt.Errorf("failed to listen on port %d: %w", s.cfg.XdsPort, err) + } + defer lis.Close() + + return xdsSrv.Serve(ctx, lis) + }) + + // Start ExtProc Server + g.Go(func() error { + slog.InfoContext(ctx, "Starting ExtProc Server", slog.Int("port", s.cfg.ExtprocPort)) + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", s.cfg.ExtprocPort)) + if err != nil { + return fmt.Errorf("failed to listen on extproc port %d: %w", s.cfg.ExtprocPort, err) + } + defer lis.Close() + + return s.extprocSrv.Serve(ctx, lis) + }) + + // Start HTTP status endpoint + if s.cfg.StatusPort > 0 { + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", s.cfg.StatusPort)) + if err != nil { + return fmt.Errorf("failed binding Router HTTP status server port: %w", err) + } + + mux := http.NewServeMux() + mux.HandleFunc("/statusz", s.handleStatusz) + + httpServer := &http.Server{ + Handler: mux, + } + + g.Go(func() error { + go func() { + if err := httpServer.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) { + // silent shutdown + } + }() + <-ctx.Done() + return httpServer.Close() + }) + } + + return g.Wait() +} + +func generateSelfSignedCert() (string, string, error) { + priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return "", "", err + } + + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + Organization: []string{"Substrate Local Test"}, + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour * 24 * 365), + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + DNSNames: []string{"localhost"}, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + if err != nil { + return "", "", err + } + + certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + return "", "", err + } + keyPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) + + return string(certPem), string(keyPem), nil +} diff --git a/cmd/servers/atenet/app/router/status.go b/cmd/servers/atenet/app/router/status.go new file mode 100644 index 000000000..c8e8be55c --- /dev/null +++ b/cmd/servers/atenet/app/router/status.go @@ -0,0 +1,274 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + _ "embed" + "encoding/json" + "fmt" + "html/template" + "log/slog" + "net/http" + "os" + "runtime/debug" + "strings" + "sync" + "time" + + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var BuildTag = "dev" + +type RecordedQuery struct { + Timestamp time.Time `json:"timestamp"` + Client string `json:"client"` + Host string `json:"host"` + Path string `json:"path"` + Method string `json:"method"` + Action string `json:"action"` + Target string `json:"target"` + Duration time.Duration `json:"duration"` +} + +type QueryRecorder struct { + mu sync.RWMutex + queries []RecordedQuery + size int + index int +} + +func NewQueryRecorder(size int) *QueryRecorder { + return &QueryRecorder{ + queries: make([]RecordedQuery, 0, size), + size: size, + } +} + +func (qr *QueryRecorder) Add(q RecordedQuery) { + if qr == nil { + return + } + + qr.mu.Lock() + defer qr.mu.Unlock() + + if len(qr.queries) < qr.size { + qr.queries = append(qr.queries, q) + } else { + qr.queries[qr.index] = q + qr.index = (qr.index + 1) % qr.size + } +} + +func (qr *QueryRecorder) Get() []RecordedQuery { + if qr == nil { + return nil + } + + qr.mu.RLock() + defer qr.mu.RUnlock() + + n := len(qr.queries) + if n == 0 { + return nil + } + + res := make([]RecordedQuery, n) + if n < qr.size { + for i := 0; i < n; i++ { + res[i] = qr.queries[n-1-i] + } + } else { + for i := 0; i < n; i++ { + pos := (qr.index - 1 - i + n) % n + res[i] = qr.queries[pos] + } + } + + return res +} + +func (qr *QueryRecorder) AddRouterRequest( + start time.Time, + duration time.Duration, + action, + target string, + m *requestMetadata, +) { + qr.Add(RecordedQuery{ + Timestamp: start, + Client: m.headers[":authority"], + Host: m.host, + Path: m.path, + Method: m.headers[":method"], + Action: action, + Target: target, + Duration: duration, + }) +} + +type TemplateInfo struct { + Name string `json:"name"` + Namespace string `json:"namespace"` +} + +type DashboardContext struct { + BuildTag string `json:"build_tag"` + RouterClusterIP string `json:"router_cluster_ip"` + Namespace string `json:"namespace"` + HttpPort int `json:"port_http"` + XdsPort int `json:"port_xds"` + ExtprocPort int `json:"port_extproc"` + StatusPort int `json:"status_port"` + Args string `json:"args"` + Flags map[string]string `json:"flags"` + Queries []FormattedQuery `json:"queries"` + Health RouterHealthReport `json:"health"` + Templates []TemplateInfo `json:"templates"` +} + +type FormattedQuery struct { + Timestamp string `json:"timestamp"` + Client string `json:"client"` + Host string `json:"host"` + Path string `json:"path"` + Method string `json:"method"` + Action string `json:"action"` + Target string `json:"target"` + Duration string `json:"duration"` +} + +func (s *RouterServer) getRouterIP(ctx context.Context) string { + if s.cfg.Standalone || s.clientset == nil { + return "Standalone Mode (No Cluster IP)" + } + + svc, err := s.clientset.CoreV1().Services(s.cfg.Namespace).Get(ctx, "atenet-router", metav1.GetOptions{}) + if err != nil { + return fmt.Sprintf("Lookup Failed: %v", err) + } + + if svc.Spec.ClusterIP == "" || svc.Spec.ClusterIP == "None" { + return "ClusterIP Unassigned" + } + + return svc.Spec.ClusterIP +} + +func (s *RouterServer) handleStatusz(w http.ResponseWriter, req *http.Request) { + ctx, cancel := context.WithTimeout(req.Context(), 3*time.Second) + defer cancel() + + routerIP := s.getRouterIP(ctx) + + buildInfo := BuildTag + if info, ok := debug.ReadBuildInfo(); ok { + for _, setting := range info.Settings { + if setting.Key == "vcs.revision" { + buildInfo += fmt.Sprintf(" (rev: %s)", setting.Value) + } + } + } + + argsStr := strings.Join(os.Args, " ") + + flagsMap := make(map[string]string) + if s.cmd != nil { + s.cmd.Flags().VisitAll(func(f *pflag.Flag) { + flagsMap[f.Name] = f.Value.String() + }) + } + + var rawQueries []RecordedQuery + if s.extprocSrv != nil && s.extprocSrv.recorder != nil { + rawQueries = s.extprocSrv.recorder.Get() + } + + formattedQueries := make([]FormattedQuery, len(rawQueries)) + for i, q := range rawQueries { + formattedQueries[i] = FormattedQuery{ + Timestamp: q.Timestamp.Format(time.RFC3339), + Client: q.Client, + Host: q.Host, + Path: q.Path, + Method: q.Method, + Action: q.Action, + Target: q.Target, + Duration: fmt.Sprintf("%.2f ms", float64(q.Duration.Microseconds())/1000), + } + } + + var hr RouterHealthReport + if s.health != nil { + hr = s.health.Report() + } + + var templateInfos []TemplateInfo + if s.atStore != nil { + templates, err := s.atStore.readyTemplates(ctx) + if err != nil { + slog.ErrorContext(ctx, "Failed to get ActorTemplates for status", slog.String("err", err.Error())) + } else { + templateInfos = make([]TemplateInfo, len(templates)) + for i, t := range templates { + templateInfos[i] = TemplateInfo{ + Name: t.Name, + Namespace: t.Namespace, + } + } + } + } + + data := DashboardContext{ + BuildTag: buildInfo, + RouterClusterIP: routerIP, + Namespace: s.cfg.Namespace, + HttpPort: s.cfg.HttpPort, + XdsPort: s.cfg.XdsPort, + ExtprocPort: s.cfg.ExtprocPort, + StatusPort: s.cfg.StatusPort, + Args: argsStr, + Flags: flagsMap, + Queries: formattedQueries, + Health: hr, + Templates: templateInfos, + } + + accept := req.Header.Get("Accept") + formatParam := req.URL.Query().Get("format") + + if strings.Contains(accept, "application/json") || formatParam == "json" { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _ = json.NewEncoder(w).Encode(data) + return + } + + w.Header().Set("Content-Type", "text/html; charset=utf-8") + tmpl, err := template.New("dashboard").Parse(dashboardHTML) + if err != nil { + http.Error(w, fmt.Sprintf("Template parsing failed: %v", err), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + _ = tmpl.Execute(w, data) +} + +//go:embed dashboard.html +var dashboardHTML string diff --git a/cmd/servers/atenet/app/router/status_test.go b/cmd/servers/atenet/app/router/status_test.go new file mode 100644 index 000000000..f5b98c3f4 --- /dev/null +++ b/cmd/servers/atenet/app/router/status_test.go @@ -0,0 +1,142 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "os" + "strings" + "testing" + "time" +) + +func TestStatuszEndpoint(t *testing.T) { + dnsAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("Failed determining dynamic port: %v", err) + } + l1, err := net.ListenTCP("tcp", dnsAddr) + if err != nil { + t.Fatalf("Failed creating listener: %v", err) + } + httpPort := l1.Addr().(*net.TCPAddr).Port + l1.Close() + + // Pre-configure local yaml mockup + tmpFile, err := os.CreateTemp("", "templates-*.yaml") + if err != nil { + t.Fatalf("Unable creating temp files: %v", err) + } + defer os.Remove(tmpFile.Name()) + tmpFile.Close() + + cfg := RouterConfig{ + Standalone: true, + Namespace: "default", + StatusPort: httpPort, + HttpPort: 8080, + XdsPort: 18000, + ExtprocPort: 50051, + TemplatesFile: tmpFile.Name(), + } + + srv, err := NewRouterServer(cfg) + if err != nil { + t.Fatalf("Failed generating router server: %v", err) + } + + srv.extprocSrv = NewExtProcServer(cfg.ExtprocPort, &mockClient{}) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Inject recorded queries + srv.extprocSrv.recorder.Add(RecordedQuery{ + Timestamp: time.Now(), + Client: "127.0.0.1", + Host: "example.com", + Path: "/v1/test", + Method: "GET", + Action: "Matched test-actor", + Target: "10.0.0.5", + Duration: time.Millisecond * 10, + }) + + statusReady := make(chan struct{}) + go func() { + close(statusReady) + if runErr := srv.Run(ctx); runErr != nil && !strings.Contains(runErr.Error(), "context canceled") { + // ignore task cancellation shutdowns + } + }() + + <-statusReady + + statuszUrl := fmt.Sprintf("http://127.0.0.1:%d/statusz", httpPort) + + var resp *http.Response + var getErr error + for i := 0; i < 20; i++ { + resp, getErr = http.Get(statuszUrl) + if getErr == nil { + break + } + time.Sleep(100 * time.Millisecond) + } + if getErr != nil { + t.Fatalf("Failed retrieving status request output details after retries: %v", getErr) + } + defer resp.Body.Close() + + htmlBytes, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatalf("Status details parsing operation error: %v", err) + } + content := string(htmlBytes) + + if !strings.Contains(content, "atenet Router Status") { + t.Errorf("Status content missing expected header") + } + + if !strings.Contains(content, "Matched test-actor") { + t.Errorf("Recorded processed activities trace text is missing from HTML response output") + } + + // Verify format=json serialization integration checks + jsonUrl := fmt.Sprintf("%s?format=json", statuszUrl) + jsonResp, err := http.Get(jsonUrl) + if err != nil { + t.Fatalf("JSON format endpoint call resulted in error: %v", err) + } + defer jsonResp.Body.Close() + + var dashboard DashboardContext + if err := json.NewDecoder(jsonResp.Body).Decode(&dashboard); err != nil { + t.Fatalf("JSON decoding task completed in failure: %v", err) + } + + if len(dashboard.Queries) != 1 { + t.Errorf("Missing operations telemetry data elements inside raw serialized response json outputs") + } + + if dashboard.Queries[0].Target != "10.0.0.5" { + t.Errorf("Target parameters unassigned inside context payload context properties: found %s", dashboard.Queries[0].Target) + } +} diff --git a/cmd/servers/atenet/app/router/xds.go b/cmd/servers/atenet/app/router/xds.go new file mode 100644 index 000000000..20ce920de --- /dev/null +++ b/cmd/servers/atenet/app/router/xds.go @@ -0,0 +1,483 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "fmt" + "log/slog" + "net" + "strconv" + "sync" + "time" + + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/wrapperspb" + + accesslogv3 "github.com/envoyproxy/go-control-plane/envoy/config/accesslog/v3" + clusterv3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" + mutationrulesv3 "github.com/envoyproxy/go-control-plane/envoy/config/common/mutation_rules/v3" + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + endpointv3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" + listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" + routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + streamaccesslogv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/stream/v3" + dfpclusterv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/dynamic_forward_proxy/v3" + dfpcommonv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/common/dynamic_forward_proxy/v3" + dfpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/dynamic_forward_proxy/v3" + extprocv3filter "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3" + routerv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" + hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + getaddrinfov3 "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/getaddrinfo/v3" + tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" + httpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" + clustergrpc "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3" + discoverygrpc "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + endpointgrpc "github.com/envoyproxy/go-control-plane/envoy/service/endpoint/v3" + listenergrpc "github.com/envoyproxy/go-control-plane/envoy/service/listener/v3" + routegrpc "github.com/envoyproxy/go-control-plane/envoy/service/route/v3" + "github.com/envoyproxy/go-control-plane/pkg/cache/types" + cachev3 "github.com/envoyproxy/go-control-plane/pkg/cache/v3" + resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" + serverv3 "github.com/envoyproxy/go-control-plane/pkg/server/v3" +) + +const ( + NodeID = "substrate-envoy-node" + IngressHTTPListener = "ingress_http_listener" + IngressHTTPSListener = "ingress_https_listener" + RouteName = "substrate_routes" + ClusterName = "ate-cluster" +) + +// XdsServer implements an aggregated discovery service server for dynamic Envoy router nodes. +type XdsServer struct { + xdsPort int + extprocPort int + extprocAddr string + ingressPort int + snapshot cachev3.SnapshotCache + srv serverv3.Server + versionCount int64 + + mu sync.Mutex + + httpsPort int + certPath string + certContent string + keyContent string +} + +func NewXdsServer(xdsPort int) *XdsServer { + cache := cachev3.NewSnapshotCache(true, cachev3.IDHash{}, nil) + srv := serverv3.NewServer(context.Background(), cache, nil) + + return &XdsServer{ + xdsPort: xdsPort, + snapshot: cache, + srv: srv, + extprocPort: 50051, // matches default extproc port + extprocAddr: "127.0.0.1", + ingressPort: 8080, + } +} + +func (x *XdsServer) SetConfig(ingressPort int, extprocPort int, extprocAddr string) { + x.mu.Lock() + defer x.mu.Unlock() + x.ingressPort = ingressPort + x.extprocPort = extprocPort + x.extprocAddr = extprocAddr +} + +func (x *XdsServer) SetTlsConfig(httpsPort int, certPath string, certContent string, keyContent string) { + x.mu.Lock() + defer x.mu.Unlock() + x.httpsPort = httpsPort + x.certPath = certPath + x.certContent = certContent + x.keyContent = keyContent +} + +func (x *XdsServer) UpdateSnapshot() error { + x.mu.Lock() + defer x.mu.Unlock() + + x.versionCount++ + ver := strconv.FormatInt(x.versionCount, 10) + + // Clusters + clusters := []types.Resource{ + x.buildCluster(), + x.buildDynamicForwardProxyCluster(), + } + + // Routes + routes := []types.Resource{ + x.buildRoutes(), + } + + // Listeners + listeners := []types.Resource{ + x.buildListener(), + } + if x.httpsPort > 0 { + listeners = append(listeners, x.buildHttpsListener()) + } + + // Snapshot + snapshot, err := cachev3.NewSnapshot(ver, map[resourcev3.Type][]types.Resource{ + resourcev3.ClusterType: clusters, + resourcev3.RouteType: routes, + resourcev3.ListenerType: listeners, + }) + + if err != nil { + return fmt.Errorf("failed to build xDS Snapshot: %w", err) + } + + if err := snapshot.Consistent(); err != nil { + return fmt.Errorf("snapshot evaluation failed integrity check: %w", err) + } + + slog.Info("Deploying updated xDS configuration snapshot", slog.String("version", ver)) + return x.snapshot.SetSnapshot(context.Background(), NodeID, snapshot) +} + +func (x *XdsServer) Serve(ctx context.Context, lis net.Listener) error { + // Ensure a first snapshot is deployed + if err := x.UpdateSnapshot(); err != nil { + slog.ErrorContext(ctx, "Warning - initial xDS setup update failed", slog.String("err", err.Error())) + } + + grpcServer := grpc.NewServer() + discoverygrpc.RegisterAggregatedDiscoveryServiceServer(grpcServer, x.srv) + clustergrpc.RegisterClusterDiscoveryServiceServer(grpcServer, x.srv) + endpointgrpc.RegisterEndpointDiscoveryServiceServer(grpcServer, x.srv) + listenergrpc.RegisterListenerDiscoveryServiceServer(grpcServer, x.srv) + routegrpc.RegisterRouteDiscoveryServiceServer(grpcServer, x.srv) + + errChan := make(chan error, 1) + go func() { + if err := grpcServer.Serve(lis); err != nil { + errChan <- err + } + }() + + select { + case <-ctx.Done(): + grpcServer.GracefulStop() + return nil + case err := <-errChan: + return err + } +} + +func (x *XdsServer) buildCluster() *clusterv3.Cluster { + h2Opts, _ := anypb.New(&httpv3.HttpProtocolOptions{ + UpstreamProtocolOptions: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ + ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ + ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, + }, + }, + }) + + return &clusterv3.Cluster{ + Name: ClusterName, + ConnectTimeout: durationpb.New(250 * time.Millisecond), + ClusterDiscoveryType: &clusterv3.Cluster_Type{ + Type: clusterv3.Cluster_STATIC, + }, + LbPolicy: clusterv3.Cluster_ROUND_ROBIN, + LoadAssignment: &endpointv3.ClusterLoadAssignment{ + ClusterName: ClusterName, + Endpoints: []*endpointv3.LocalityLbEndpoints{ + { + LbEndpoints: []*endpointv3.LbEndpoint{ + { + HostIdentifier: &endpointv3.LbEndpoint_Endpoint{ + Endpoint: &endpointv3.Endpoint{ + Address: &corev3.Address{ + Address: &corev3.Address_SocketAddress{ + SocketAddress: &corev3.SocketAddress{ + Address: x.extprocAddr, + PortSpecifier: &corev3.SocketAddress_PortValue{ + PortValue: uint32(x.extprocPort), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + TypedExtensionProtocolOptions: map[string]*anypb.Any{ + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": h2Opts, + }, + } +} + +func buildDnsCacheConfig() *dfpcommonv3.DnsCacheConfig { + resolverConfigAny, _ := anypb.New(&getaddrinfov3.GetAddrInfoDnsResolverConfig{}) + return &dfpcommonv3.DnsCacheConfig{ + Name: "dynamic_forward_proxy_cache_config", + DnsLookupFamily: clusterv3.Cluster_V4_ONLY, + TypedDnsResolverConfig: &corev3.TypedExtensionConfig{ + Name: "envoy.network.dns_resolver.getaddrinfo", + TypedConfig: resolverConfigAny, + }, + } +} + +func (x *XdsServer) buildDynamicForwardProxyCluster() *clusterv3.Cluster { + dfpClusterConfig := &dfpclusterv3.ClusterConfig{ + ClusterImplementationSpecifier: &dfpclusterv3.ClusterConfig_DnsCacheConfig{ + DnsCacheConfig: buildDnsCacheConfig(), + }, + } + + clusterConfigAny, _ := anypb.New(dfpClusterConfig) + + return &clusterv3.Cluster{ + Name: "dynamic_forward_proxy_cluster", + LbPolicy: clusterv3.Cluster_CLUSTER_PROVIDED, + ClusterDiscoveryType: &clusterv3.Cluster_ClusterType{ + ClusterType: &clusterv3.Cluster_CustomClusterType{ + Name: "envoy.clusters.dynamic_forward_proxy", + TypedConfig: clusterConfigAny, + }, + }, + } +} + +func (x *XdsServer) buildRoutes() *routev3.RouteConfiguration { + return &routev3.RouteConfiguration{ + Name: RouteName, + VirtualHosts: []*routev3.VirtualHost{ + { + Name: "local_service", + Domains: []string{"*"}, + Routes: []*routev3.Route{ + { + Match: &routev3.RouteMatch{ + PathSpecifier: &routev3.RouteMatch_Prefix{ + Prefix: "/", + }, + }, + Action: &routev3.Route_Route{ + Route: &routev3.RouteAction{ + ClusterSpecifier: &routev3.RouteAction_Cluster{ + Cluster: "dynamic_forward_proxy_cluster", + }, + Timeout: durationpb.New(10 * time.Second), + }, + }, + }, + }, + }, + }, + } +} + +func (x *XdsServer) buildHcm(statPrefix string) *anypb.Any { + extProcConfig, _ := anypb.New(&extprocv3filter.ExternalProcessor{ + GrpcService: &corev3.GrpcService{ + TargetSpecifier: &corev3.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: &corev3.GrpcService_EnvoyGrpc{ + ClusterName: ClusterName, + }, + }, + Timeout: durationpb.New(5 * time.Second), + }, + MutationRules: &mutationrulesv3.HeaderMutationRules{ + AllowAllRouting: &wrapperspb.BoolValue{Value: true}, + }, + // Explicitly configure the message timeout to avoid the 200ms default + MessageTimeout: durationpb.New(5 * time.Second), + ProcessingMode: &extprocv3filter.ProcessingMode{ + RequestHeaderMode: extprocv3filter.ProcessingMode_SEND, + ResponseHeaderMode: extprocv3filter.ProcessingMode_SKIP, + RequestBodyMode: extprocv3filter.ProcessingMode_NONE, + ResponseBodyMode: extprocv3filter.ProcessingMode_NONE, + RequestTrailerMode: extprocv3filter.ProcessingMode_SKIP, + ResponseTrailerMode: extprocv3filter.ProcessingMode_SKIP, + }, + }) + + dfpFilterConfig, _ := anypb.New(&dfpv3.FilterConfig{ + ImplementationSpecifier: &dfpv3.FilterConfig_DnsCacheConfig{ + DnsCacheConfig: buildDnsCacheConfig(), + }, + }) + + routerAny, _ := anypb.New(&routerv3.Router{}) + + accessLogConfig, _ := anypb.New(&streamaccesslogv3.StdoutAccessLog{}) + + hcm, _ := anypb.New(&hcmv3.HttpConnectionManager{ + StatPrefix: statPrefix, + GenerateRequestId: &wrapperspb.BoolValue{Value: true}, + AccessLog: []*accesslogv3.AccessLog{ + { + Name: "envoy.access_loggers.stdout", + ConfigType: &accesslogv3.AccessLog_TypedConfig{ + TypedConfig: accessLogConfig, + }, + }, + }, + HttpFilters: []*hcmv3.HttpFilter{ + { + Name: "envoy.filters.http.ext_proc", + ConfigType: &hcmv3.HttpFilter_TypedConfig{ + TypedConfig: extProcConfig, + }, + }, + { + Name: "envoy.filters.http.dynamic_forward_proxy", + ConfigType: &hcmv3.HttpFilter_TypedConfig{ + TypedConfig: dfpFilterConfig, + }, + }, + { + Name: "envoy.filters.http.router", + ConfigType: &hcmv3.HttpFilter_TypedConfig{ + TypedConfig: routerAny, + }, + }, + }, + RouteSpecifier: &hcmv3.HttpConnectionManager_Rds{ + Rds: &hcmv3.Rds{ + RouteConfigName: RouteName, + ConfigSource: &corev3.ConfigSource{ + ResourceApiVersion: corev3.ApiVersion_V3, + ConfigSourceSpecifier: &corev3.ConfigSource_Ads{ + Ads: &corev3.AggregatedConfigSource{}, + }, + }, + }, + }, + }) + return hcm +} + +func (x *XdsServer) buildListener() *listenerv3.Listener { + hcm := x.buildHcm("ingress_http") + + return &listenerv3.Listener{ + Name: IngressHTTPListener, + Address: &corev3.Address{ + Address: &corev3.Address_SocketAddress{ + SocketAddress: &corev3.SocketAddress{ + Address: "0.0.0.0", + PortSpecifier: &corev3.SocketAddress_PortValue{ + PortValue: uint32(x.ingressPort), + }, + }, + }, + }, + FilterChains: []*listenerv3.FilterChain{ + { + Filters: []*listenerv3.Filter{ + { + Name: "envoy.filters.network.http_connection_manager", + ConfigType: &listenerv3.Filter_TypedConfig{ + TypedConfig: hcm, + }, + }, + }, + }, + }, + } +} + +func (x *XdsServer) buildHttpsListener() *listenerv3.Listener { + hcm := x.buildHcm("ingress_https") + + tlsConfig := &tlsv3.DownstreamTlsContext{ + CommonTlsContext: &tlsv3.CommonTlsContext{ + TlsCertificates: []*tlsv3.TlsCertificate{ + x.buildTlsCertificate(), + }, + }, + } + tlsConfigAny, _ := anypb.New(tlsConfig) + + return &listenerv3.Listener{ + Name: IngressHTTPSListener, + Address: &corev3.Address{ + Address: &corev3.Address_SocketAddress{ + SocketAddress: &corev3.SocketAddress{ + Address: "0.0.0.0", + PortSpecifier: &corev3.SocketAddress_PortValue{ + PortValue: uint32(x.httpsPort), + }, + }, + }, + }, + FilterChains: []*listenerv3.FilterChain{ + { + Filters: []*listenerv3.Filter{ + { + Name: "envoy.filters.network.http_connection_manager", + ConfigType: &listenerv3.Filter_TypedConfig{ + TypedConfig: hcm, + }, + }, + }, + TransportSocket: &corev3.TransportSocket{ + Name: "envoy.transport_sockets.tls", + ConfigType: &corev3.TransportSocket_TypedConfig{ + TypedConfig: tlsConfigAny, + }, + }, + }, + }, + } +} + +func (x *XdsServer) buildTlsCertificate() *tlsv3.TlsCertificate { + if x.certPath != "" { + return &tlsv3.TlsCertificate{ + CertificateChain: &corev3.DataSource{ + Specifier: &corev3.DataSource_Filename{ + Filename: x.certPath, + }, + }, + PrivateKey: &corev3.DataSource{ + Specifier: &corev3.DataSource_Filename{ + Filename: x.certPath, // Assuming combined file + }, + }, + } + } + + return &tlsv3.TlsCertificate{ + CertificateChain: &corev3.DataSource{ + Specifier: &corev3.DataSource_InlineString{ + InlineString: x.certContent, + }, + }, + PrivateKey: &corev3.DataSource{ + Specifier: &corev3.DataSource_InlineString{ + InlineString: x.keyContent, + }, + }, + } +} diff --git a/cmd/servers/atenet/app/router/xds_test.go b/cmd/servers/atenet/app/router/xds_test.go new file mode 100644 index 000000000..189914c24 --- /dev/null +++ b/cmd/servers/atenet/app/router/xds_test.go @@ -0,0 +1,212 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "context" + "net" + "strings" + "testing" + "time" + + clusterv3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" + listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" + routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + cachev3 "github.com/envoyproxy/go-control-plane/pkg/cache/v3" + resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" +) + +func TestXdsServer_UpdateSnapshot(t *testing.T) { + server := NewXdsServer(18000) + server.SetConfig(8081, 50052, "10.0.0.1") + + err := server.UpdateSnapshot() + if err != nil { + t.Fatalf("UpdateSnapshot failed: %v", err) + } + + res, err := server.snapshot.GetSnapshot(NodeID) + if err != nil { + t.Fatalf("Failed to get generated snapshot: %v", err) + } + + snap, ok := res.(*cachev3.Snapshot) + if !ok { + t.Fatalf("Snapshot doesn't conform to type *cachev3.Snapshot, got %T", res) + } + + // Check consistent snapshot + if err := snap.Consistent(); err != nil { + t.Fatalf("Integrity check failed on snapshot: %v", err) + } + + // Verify clusters generated + clustersMap := snap.GetResources(resourcev3.ClusterType) + if len(clustersMap) != 2 { + t.Errorf("Expected 2 cluster definitions, got %d", len(clustersMap)) + } + + if raw, exists := clustersMap["ate-cluster"]; !exists { + t.Error("Static 'ate-cluster' is missing from clusters") + } else { + c := raw.(*clusterv3.Cluster) + if c.GetName() != "ate-cluster" { + t.Errorf("Expected name 'ate-cluster', got %s", c.GetName()) + } + + // Validate Endpoint address mapped from Server parameters + eps := c.GetLoadAssignment().GetEndpoints()[0].GetLbEndpoints()[0].GetEndpoint().GetAddress().GetSocketAddress() + if eps.GetAddress() != "10.0.0.1" { + t.Errorf("Expected address '10.0.0.1', got %s", eps.GetAddress()) + } + if eps.GetPortValue() != 50052 { + t.Errorf("Expected port 50052, got %d", eps.GetPortValue()) + } + } + + if raw, exists := clustersMap["dynamic_forward_proxy_cluster"]; !exists { + t.Error("'dynamic_forward_proxy_cluster' is missing from clusters") + } else { + c := raw.(*clusterv3.Cluster) + if c.GetName() != "dynamic_forward_proxy_cluster" { + t.Errorf("Expected 'dynamic_forward_proxy_cluster', got %s", c.GetName()) + } + } + + // Verify Virtual Hosts generated inside Route configuration + routesMap := snap.GetResources(resourcev3.RouteType) + if len(routesMap) != 1 { + t.Fatalf("Expected 1 route configuration object, got %d", len(routesMap)) + } + + if raw, exists := routesMap[RouteName]; !exists { + t.Errorf("Route name '%s' is missing from snapshot routes configuration", RouteName) + } else { + rc := raw.(*routev3.RouteConfiguration) + if rc.GetName() != RouteName { + t.Errorf("Expected route name '%s', got %s", RouteName, rc.GetName()) + } + + if len(rc.GetVirtualHosts()) != 1 { + t.Fatalf("Expected 1 VirtualHost definition for static routes case, got %d", len(rc.GetVirtualHosts())) + } + + vh := rc.GetVirtualHosts()[0] + if len(vh.GetDomains()) != 1 || vh.GetDomains()[0] != "*" { + t.Errorf("Expected domain '*', got %v", vh.GetDomains()) + } + + if len(vh.GetRoutes()) != 1 { + t.Fatalf("Expected 1 route in fallback VirtualHost, got %d", len(vh.GetRoutes())) + } + + fallbackRoute := vh.GetRoutes()[0] + if fallbackRoute.GetMatch().GetPrefix() != "/" { + t.Errorf("Expected path mapping prefix '/', got '%s'", fallbackRoute.GetMatch().GetPrefix()) + } + } + + // Verify listeners generated + listenersMap := snap.GetResources(resourcev3.ListenerType) + if len(listenersMap) != 1 { + t.Fatalf("Expected 1 listener definition, got %d", len(listenersMap)) + } + + if raw, exists := listenersMap[IngressHTTPListener]; !exists { + t.Errorf("Listener name '%s' is missing from snapshot listeners", IngressHTTPListener) + } else { + l := raw.(*listenerv3.Listener) + sa := l.GetAddress().GetSocketAddress() + if sa.GetPortValue() != 8081 { + t.Errorf("Expected port 8081, got %d", sa.GetPortValue()) + } + if sa.GetAddress() != "0.0.0.0" { + t.Errorf("Expected address '0.0.0.0', got %s", sa.GetAddress()) + } + } +} + +func TestXdsServer_UpdateSnapshot_WithHttps(t *testing.T) { + server := NewXdsServer(18000) + server.SetConfig(8085, 50053, "127.0.0.1") + server.SetTlsConfig(8443, "", "dummy-cert", "dummy-key") + + err := server.UpdateSnapshot() + if err != nil { + t.Fatalf("UpdateSnapshot failed: %v", err) + } + + res, err := server.snapshot.GetSnapshot(NodeID) + if err != nil { + t.Fatalf("Failed to get snapshot: %v", err) + } + + snap, ok := res.(*cachev3.Snapshot) + if !ok { + t.Fatalf("Snapshot doesn't conform to type *cachev3.Snapshot, got %T", res) + } + + listenersMap := snap.GetResources(resourcev3.ListenerType) + if len(listenersMap) != 2 { + t.Fatalf("Expected 2 listener definitions, got %d", len(listenersMap)) + } + + if raw, exists := listenersMap[IngressHTTPSListener]; !exists { + t.Errorf("Listener name '%s' is missing from snapshot listeners", IngressHTTPSListener) + } else { + l := raw.(*listenerv3.Listener) + sa := l.GetAddress().GetSocketAddress() + if sa.GetPortValue() != 8443 { + t.Errorf("Expected port 8443, got %d", sa.GetPortValue()) + } + + // Verify TLS config + fc := l.GetFilterChains()[0] + ts := fc.GetTransportSocket() + if ts.GetName() != "envoy.transport_sockets.tls" { + t.Errorf("Expected transport socket 'envoy.transport_sockets.tls', got '%s'", ts.GetName()) + } + } +} + +func TestXdsServer_Serve_Shutdown(t *testing.T) { + server := NewXdsServer(18000) + server.SetConfig(8085, 50053, "127.0.0.1") + + lis, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatalf("Failed to create tcp listener: %v", err) + } + defer lis.Close() + + ctx, cancel := context.WithCancel(context.Background()) + errChan := make(chan error, 1) + + go func() { + errChan <- server.Serve(ctx, lis) + }() + + // Cancel the context to trigger graceful stop + cancel() + + select { + case err := <-errChan: + if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + t.Errorf("Serve error returned: %v", err) + } + case <-time.After(2 * time.Second): + t.Error("Timeout exceeded waiting for Serve to finish graceful closure") + } +} diff --git a/cmd/servers/atenet/atenet-diagram.png b/cmd/servers/atenet/atenet-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..c77c5baad5b7ce9729cf68c67aa127b889a78bad GIT binary patch literal 75853 zcmcG$by$?^_CBtnU=S)I4Jrys4UM#bbb~YuCEeYif^;`S*U;S!5<}O}-8C?D*Y{=b zea>&6v-kO2=lt=zF8@+z=6ToiJZs(SzVG$=N=pi1JSKR2=gu7r5#i6WckZBU-??*7 z_aQ3qH-&KQ=XdUWyCd?M_lpB~D*-Lyg}}wp_jlA<(N)UTaq;=@pBW~o11ha z@czSXQRNcp7XmW>|NZ&mkQ>!<8qa2J))x($bFQ{t<0inxJ@F2QK75VuVI6$s>rC_d z^#a%0?9^uZ%)Ip6YvY%c5jjY@E-kqNwQ9_H0^RPY?SAS`HGaN_ohBvv{nv=T$z4KRyl$*oNHvC)CQ^$MK{rOfF^5a7 zw3|s)P_@|MheLHeU8*0fmWE9ssWcY+l#j1DluYO?E!X*a+Gdoh*;%FI!D?p0T;PqE zsHhVeEp0(1cDEJeZqV%lIm_QGp@j*T;{n??c%E-7fTcNDQPr=JAy87jd0Z-378XQfK}~ zTwI(}9eCtUWrNudeyML{bw#77s~c@LhTKyXb~2OPN`7#^ep~0T94hps-swpC;JVrx ztCGpwsLOmo%T5vqai2JZY2$FA#XG-*!ZSqp>&^954!<|%P4b9zv36Sxq&XOPfX8x? z?`0OxUC#Ee*sNE@ZTFW&sG6|(e#HSx&rMHHpL_h`{WraX>R#t~(P&CGy{mdL+Un)| zD$Fsu5)WSwHZ2A76m&&=IIut4UrDlE1cMo$$^wUOA zi^Fx9kzB<>p6Ab>H`pP!DOY`id*$s~nln);YS{A@|x>C8RQP3LN*B+3Ky= z`rLaN-g$-?=*`sFQo3JXHd4HO%fyI623!Xm_7#vy*}8q2P_Tl2UwrWo*4J-KnzNdN z?p`rJ33OH&dF+*d())~0J92xfk_uLK6Ut$agz9}ufA5#dps|;w<*mhv!t(m9(>F^V z#ic&ze)bdBaj9ajgs0CDO;r@+onU( z_5Cg!Qqr5*R002My6&K-eA=NvOmgo%cFLSCCd&D`xDAWv zGTHAX&AIB!z9q99Z5NkIQ2c1%Q@%PPHmlD#!0E@LkQ`-2p#Xvs`JGZGwbh?dujjNM zy~i_TUB5eu1`q#KjN(OWZ1HP_6};noxlGBc8EPuNhp!v6n2krXe*JtxN~iPNr!9?S za=v8qNG5U`KG5Y8Hj!?0yV6)%Ts)6$ek~|ZYmc06B;j@$r= z^zLNb#`P1h*XE0X+4vz>4|+u!FZac$xQHD0+HmvB%B+?GS#yGjIaD@0Kfl3~X!!K~ zUY2RF<8AJMJ|h#n)Q*yQRd;=kpnMJvxITnSZI+LLONaO+UKK;0hS5)3bpRQA-%bnqC!gOn2HOh@5yAru-*_{rv%4y@9UZuk&9I_uC;?120BUCzZ zV#1iIwJ$_>DtEteGoH)dTks~$*=f81U&AbSYInHH&F8pn&kqf$K&N{!(h=lL?TS)i z-M*hb@wt}kZZjI**%x)I&UgDa#X7J&*BH&OS3u}KsH5mZ><-=A8g_X|`beF(=#M(c zg44(4=lwwqAxH12f+nSYeGle77uIUEStIGwL-ofSTA!_VzA=fC5WT!S=pVAVxW3p? zoT@Ze1Qyevf2E(~3OzsB0a-pP?hZin;p*qU$ZIXDoOSA+bQhhkLXQ7*@Num>-^^72 zW9U70*v!scR-1ENBkpG(E&+~Ew^bsLT0>nkhvRR0Vi`+F$b?(g$%2T1^c;@Xh{j>J z6%unc>%60UF|apevhwr5!kzYVE}0iazQRQLOydSK2G+duyrFT`vf%>Bady>ob9&_n zY-_&GbG}P7(AjM=ZbDB7?(3J`FSSa=+J-qYe7$TC3HB)mgYlviU}1%C`@h{q;Y3U` zlR0Ejf$OUDU3($S@XHWjzet$vwv-Hqkh4NZns{1pFNKM+!COPUd~kcn+*h z#*3QSp{Q8UXbrb&3Z5P}|CcnJP}k8sWlEtSqRm8SWGL-DcJsb?wh`0HnbnE4qcM%b z#l=O=i@Nnx|JIH;7{yyg%bvjvYI@GVVC$XPMyDgAT(vM1!9ho*@p1fUd}j4TS2dTtHtm6#GoWU^vK;2bjZw*i zi3y&thsgSWaAC=7T<{|Nk}aFD?9O!K{k^^0b1+RvY}$I~$&$Ov#dc+bD-eI7q29SW zcoyl17$Q>Aor(U44{~pbVc(TM^^71&^m=npF$k8aoWB(dJ;%m=$Bl6L$aBE>jPG&@ z*dh5yN_i*dC%1V@i(szN{pMiweM&ouS1nKqWt{^jP4R3w(b+DZG6uSQ7%59beTbzH zNWi>5a*yj|+B%2t=i~h*{n7ZhXe2DwD_t2Xm1Z>M@95@%S|6dKZaX61-~wd$FB2uY zax|(Hhg|5XNnAl5(GO3lH}Va4W@;<9tgkQ6!gjVR=c2Bb#-WBVew`G)pTqkr-77>g z9$o}*I0rT-N$Q%KDjZHf2XY=i3crILOu%+<>iLx%2y0vXHum)QH&GD)0N}5++b-#9 zyKjj?|ERplX`UthXnRT#xx<01;vbUDF>C}%|2qs+(y3-o?%gJo=g~z{)NwGIGzpHr zyRgqD0^8Nx+~UQ3wE+GR;iu+T6O>>iDLYu{rYJ^t9Fl_OnNs+}j3%LEaqdWQE_)1i@ED(FEfpsQ6fV$U`8VE?^XzE04Lw$uVAov3yUrfDqI7sMvDWkr7KM7IWGo)s$IkA8OWe?9{>8 z(fAm`%ZKvo%vnEbXFQ1o@nJu(sOnf0k z#d93Yo92WPnoff1cKM{(!S{ZpZ^qI*%@m7x|C%PQ2l?3_7Zl~nd36Xci67_v5l}48b0}h^M7myTy4Lv;eB; z=n{MQh^Wp-Tv+&1qup(4CR^r=C;8l4jsLA5jig7j3YS(b%WAEU#tU4?D8XSQuUTb0 zRzOoePi}CY73ZI-fQqGJX2U47g;Kt?THTbM=16(XW4Y+bNteo&<4AO<)9RttpUCAp z1#K$>kdHEV@Y%0>Hk-pAl;LJ9AKJdC2sa`MYQN&=qf3(oqk)G-Q~u61N}O+26mY83PDyOt9)Q2pZQL#p zV{SS*0~>rnrO<;Ly*Gq&=5)BOMJ(3%>RXE7>>=csR=vhyXfO5d1|H4aH0qL_CUFg_ z7TZ&JL9hn{15fzu&iN7IT_MYM_R$fA=P4HW#cEe1Vu$)RXSR1dDuKae)9y>hd7|}P zo*i_fJpE)XaHuNYTb9~J=iugYq>JI{;w2wX;=M|~%I zFlzdoJmu2s%s7iAtYLzswv^h!k46J~tjzErhn$1V&q>^_Zwn`|h?7ZcShlgr#f$o$ zfEb<;?(u+?AX9PZge>Cw(6O>K{CW=J8JCa(WB81w$w$u-A&dY$ER3+)KxiN_u9Tw*>YAi;# zHW__sDBTiN=kS!DCXx`(GEdCkQ0Ty!2msCCQF^8%_v>o&sj?V5b?nG#{`VwGSIpZ4 zOreb%(75GhQpa6oS%ij^u%JiGd@E{CEn#j+*IPEadmJh~!&x%?sE+*p_+@;2(F9v4 zpd%YFybRH>WYA^W{yq>XdEXk??pArzNiES{YwI|>vMpZjfV&5I|SfofX;QO_cCPYP0S{~_`wX24gLG17>TMf}2^jBM&Y(KtSjPLVz-6Y@o z5E^DEgl&_KXcn0Q<-Dp_JdIT%M-x=6`ypbJiHzWJHI{L|b_d2!F(w_rm*kOC~ zBpig?w}37n1jiv9rI#}lcU3O4`5WTHEZv(T$+5H-X{42saJ`pg-L)tFXte2Rk7^vn zZ&$#TN@vtCeYSfi&}MjGor!Z?yNlgAiJWc?Z*YPui3=Lpa(zj^ZP4epf=22x5MJnf zg4Die(~ZK%_n;w3pZ~LX7iI8r6CPofp?Bw~A>ERLudnMX?oFE*&GhOuD%gC~I7wOu zg6UA+yIK%zUnda+{N}ekR?TU8fdt7GY66G7Z>~-2Z!kbOMR{>WnV&_0fY)N9Zn&&O zD!LdNeE$}m9WyHlV@2=rb*;kS4qyiFznL+e+*76t%p~b00Y%Xjkw8anu-1JiZN*Xi zqO@uvUrKPi#>YYyTknMfon+S?;|!;e zstA%2*7Mj&#e7cxK9@5L1&R$N+(XI#ii$--t%tv)*Q8kk>u>V890zG<73>KTeM0AD zH=2HiX5;R#)z6tI;v~*-ZmnU_{J^RK0Jo7k8}!UQ+uac#$TpO2dKmkaE>MBPaVP_O zkwVv}sAl=|uvf^jNwZet%NvEI_#)Cv63sH_R>xMQ^lFJ(v+QqIKqD?Pv@84S!v_%+ z>SXb~=l3lMKorv`3xj_-Q*!sPgdN_uc^HfpsOvVpjQyh*|FL%lbl3(?pa|xCP{+1XLYale62Tbt=ofbqPOIZHzskIjeRdRWH|K^ zg*ZpwGpxq7TxGJirJqdbJOt1?DT5Fd(&D40l2&%z+Jz9kp z#6NckG-e{=ZQRl=2~kMCJ1DiU3#w`_4W456ZjcQ=z9RwO+sB6SiG5qv#uR4-_bjUQ zLJZf>^i#g4ggu(i_)EF~{ztg$l^NuF z#4Rn8nAZfbAwC#-MLw^US9l-3eyjW6J|5H?V4OBTNeGwBb7;Gn3!hpe&)ahTCJs#G|#&<{)#)~RTw}^xLd7s>^UOi*(yJFW0XkK1Dg#zq&b9%Z~Fc@F?gc8rXMcUpN@groJ8@k|J;q5Wxo7UwbPN?CYn4czqkm3dF%tm5Ti{SQ@Zy`g?kV!6 zKAyd}_9$Uoe2;Ur8AqmCQOK=Ucj{?KDY9CmduSj}XFl85jYBgzT=((IA#heV?oP## z2R>!}?gkS!XtHJ07NG8=#9Dly`;~x%?+x)kzig&!&0;ybGklIQ@NK6WOE5vk+1H@bSh0|M{=iH_31c@?IRduLvK@D?EA#a%ujfR#RMce%6 z%)oCcYrg)+Sp8sNz`%MPin-%@!#ja*8R2KP-Jr8OKPGV?%-3@K2>VMcKnpU1p5v(h zU-60c@(vO9K54i~-U|3ADo}|@3NU?L z^tEx=xxnh`^GW++gCG^>)q@BsuXVj)6rHXj-{a?@c-e1F_3=Q>ssfPXM$0(DAr<_FQ zwCP5xZlq}U^j79*XNak87-sZ$$jJ6Rso*xq_rL$g9b3h~p?{al`8N;R%@FvuY#tKx z=e_<3soI*5FFlS{-bhJx>-LwQ^}J8Tl|N7xF8vMhzkQW1Q(WR)VHEdeOpWtg_b9ss zH@x9ITYuzSydB1}l*Sb%IbA<(hkN5#y3eO7%;W?_Bczo}_2l=et-EjJ z6!W5NPmt~sN5squIPcY3D_zfWMur3A5u7lC*_1S+$pQ}odj#JEIB03BP$8||XoD=+ zdB4EfuF_~^<#8kxcja{#TWh8(k$|b;UibQc(HJn?cpwp z#Nwa?ncwo*!n8fPf^H<*e|b~_<{`1x%SyI!<3PF$&)1VXu=$$)! zmoEGIAv)-50F04dUhN<0A5TVE&cvB#j`9H2=mdiLos+0=k+d>w?%sX2+zTyjxPkYA^v00y2NcbBzuFPJ1T{h9BxS70#oDfts7efOuVu{lu$4F`ouq`puavjRp18kzP%h{0Kwg2nZ&_}pb zn8ZfDG&?jM6{jJgYZAqJ`EMBc`08|OT5y--2?!mugb9!d9&B%%JdJop1ckX?w;96eEwCDeSZv@#yWD909JIB9#} zfZnQyB-A5ab%!5-I;~VBoO@9Nzgko;pZ`n)RbRLaX-|&bm?w25l4S; z>VbxQK|-yrhq0bmaB%E`(4plsLJ6Pu4*+8m;=>D|#D5107&R{>oSj}^L$BQ7nMtmK zL3iNS?Cd#WYa}FN+1`%jAw~@AkSv znCjBY<1c<)knU$RTOec>;Kq}MiQHmQ-ja!{ove1(rfU@^n9|X|XW6@B+a^9fBLDdz zn4woo@5F|`tD4JukL4AQCiIux6qzNMTpSVGD%Bw$dpcQ72

}A-$Cfy;nh%laynKw+ZD~R^&z=a~ItSVHqXN9_rMuxjtXO_FIPdY-aroGz(<;uGw z_Et>Qvco31biDN4brW3G;m|_?H*|z-KgM-;@jHQZw)tPp7MOYZwpV?GHB$ zSg<^D4bn2>`yEQ>`CA$u`r>0rl7Qo29)8x zG%R+226?Yp!@^`P)Z5^!dPrP2l~)~)C0NUPvW?nKoPWOv6l2SD1B>7PcswN37o_HX z0PQUafbJko2fvVRT(t*W+`wk{A_9biuTQEJ=n!}@pwjbFk3UM5Bfo(7-;^wafeeQ6 zvYWY^tEAXvcxgX(?rL8`?)6FIO>FL^tP$*S*blAAgOBlcp2MNud%5mn&Q;8syDhrk!ZD%=|v&C>l_%-$-`Mt7s6!K-~3c>lC(I5~xDZ+l* zAx(wLCW~@A2Jz<6qs^J0Px6;ydo~C8kEbqD{f8?Mh0)ecVxC(;mW9eSWgyaHf0whx zCEeuedPe;m=RW+i&#=N|FYuafk{zY=f88x$)ODXAMqt$g_&Oc zl+efRa!<$>;G}W@F{ED&$K*jv8NWIEW#USnBhO~h`0Ed1sE}iGg@P{v*x0VC(-K#Y zalWLuoVj#&G6!og%un0&d7wI0xE@5Qwsv3{O$<#IisUosdg>rX9fxXJjow~dTeUq_ z9)%Lq+?hT*?vG6?VVjFi$yYfWGMLQ%^q>2>e*@)A>$3P?C+8fNFxYM)#4p4^^=}au zM+ge{6XcAso=B-Lub&C_341<-pk`0mr^8@sb7q!9_vggj_%`^o_FUIozpL~+c$&ia;x(3{ip#H zWZi1}omon6omX1(;qbl$4qZ~fLiKXb~7Tz!NtoLo1#k}f{YmiTw+;|aVWEvV8PwjH>XQj6BV)#M_{`HuAPqCq;Oe2IIF?>f`-5Lw6D9p-7=$VaY3CqY(s;sVaGYIyX>6s7Y*>6D z7;2b#FY=G#{uh$#-}}|U)Z^$-4{${nde%1(dGU{DYEi*^~tXZ$T@Xyzh+`n{&y^{wt>=k#KtxAWzMJvwA z4IaC#n65b1LLzL@0>?V;6M)G+8+tW7Kz0TER=6%e?OQG87B=iJO9&cn!;yv5a6Ia$ z1n1)7EDav1^YC!;&UrI~)B?ElMPQw^^YLLu3OTW%PCSFXd1HU)6UMn;)q<<^Gn(lR zCOkE+&Qk0~@WCV!#BB98iwGQAFCR!Sln!2Nd$=#0G*Mp*3j7~$Gt5U4F`ONaXEt0_ z`;&apAgDm%0`QW&Un{d%;FIEBPw^%RvjyBD(JMgqg^{{b3mT{EG)+Sobp4ivBpOB$ zg-NcnB1i{Pm)-B|fQEXR6mM84pBq(oUs%#WQX@}^{!An8xWaUbpgK&x6>?mOOC2(4 z6Y$(!Zf92emk=8&ffs)H*vE>*U}BVC%^hSQqjoH|6|95l8a;{5v1~9`xy}5ijm99( zaWtqdWAMf*f&(etw!ao_9plu7W91@F>|H%il^Dn8ICi)ZrWkju#%9$)g#7rjhdatR zf|iDC0de)e-ax!TLqJyTmIBgQEucb<2~X1y3u`0DLWswH-Ah+2`K=b8f!RK+SJA5V;WIyMsxKFM> zDHE=d`uUN3mh@}-ZF0KntcjcbZqU0Mz%{2!isVIx$yq^XW?W`pppNmoRT{DyU&~2< zjyo3SjXU;E*om#CEp2xE7dq@Oy!T%_8X_|Gd_b?GR4h2!Rbq+u#_YQ&O`Uaz)4xVr{IR0@;b#igIEHaG9;#EQ>n>73@p3 z)rw2E*+{;sqRNv`Oxp`+5*(4S|1}9pV8bS8LvWt5GzSn{jzqVfII4}wvYX>6b6GLB z<_EYPXVn>*V$NqP(Yj|%-%(2HOePpK63u36L`awWd2XhoS4U$R_0yF((2oGo`NO<> zjETLw^D=+w6>tZYq5zCT1>-w#&Ciz06on{@H3FV75utDwA1K#lvSB8J-2YOx%@U6j zxtzQ9Cd-X8S9@a9Agt!J?RbVLsOY=Z3V1qr=7-;55e9&FEUU2kEK(7?(S34tGABj= zRpfWKL?`n8umWK=UhNK#*Mt@)6fnbxHa?O-`qP3hR(s=gNo>Veyf$WEZ4pjsMmQ2Z z0pZdKIk)-YWW-(qI6$}0R{Vqa-4oGh+U>YpE@rryCSh9TV-wgGiPj*~oR%h+t*x9&xEirhXH zYxALW-x$L@n2jlbh$B8MO!F~19Lh-v3qO?$xQm!BU+CP(hz5tbAgdSlwC|K}e|*^# zzaNt}L(|h1q;dwBCvpL^r}U6!51`*s!eDlETc^~MMf_R4usu3~_zwX-!BG#Gwu_$> z`2M5y&?M)|WS z_b)wVt@R$`Y)TG4hxao~R*q>zQU5}&^;v`M_)gKtf`Yd(F|BphLI|taW2=C5CUk0V zcfi$T7_Bb9d0WbC4pD*yv^2Sxif<3N?Q;p|fbYiIzbg-a*5&>reypKEpZ5L&Y6EY% z!Qh))FCKmwhVI&~M@tfB(#I{U@p-y#ts;IZ0P8B3o_+w54u{)iRoOg$(g6Sj#Txg4 zBiFSD1AH>N!tf`}@BbrduQY~lOBFm!OS3f2tVZNqUI%k; zb0oLhVB^8#7t*+3hm>33nXz+1Q#t(xr66UC$j_1A&?2J`5Y;|Cd+Bx0*@3amr(gx0kyAc?S}N8&9xEx%0rT zNAgFzEm*nl#GgUs}?L`_H@YvcHM2p z{9CC9VrYeKM1>Q_ZWbj#ZgkQfN){Zq8tUnlpC**cuG_7BM~Ko-_g|FR-%dcH@JfaA zT+t9;XNfnrG-2XZvnbX(`<-hU8prvNND@=ei~5@h{iN)A=aVj%`54&6t&5JB!!E+G zpUxEz`h@?+j7h%{@ONfBVuR950rsSGz;~Q~^#J=eK#URqHS&UBs?2JoUmTFJ`1{)f zn_2!4ZvHGh|JJ~Kenae}o++xBrIq3Bw|B6k$hLHlwSwhpkpBdSs?r_m7nzfc8mMZL z@6W>LxC6l8euj{7-~?tI6PC{dvk(#7Q+PO>fRQ~1aG>UBwRq(KWk}XPD0H~ebP5V~ zT){b-v7b}E=n=ow=z5txK#rx~YXntQVLR*feZ@X|T57*49vKmHx^p>OFBbc|3iM}9 z8jv4jy(pe%E9LVl#U7LJXNpaDg&QU{F1%x-fE+iS0^Q9pp?TfwtCnbxMgh5aOtRAn zGM~0){f&Iimk*INsx0_8#8=&eHm;k)*$ites7f3TyUFK3)0OY)h5epG>P7G8+eKxY zhqksR@qkNO8N%LLf0|Hyukt0(VCG!%U{QMT-z59rBIikXvUMghW3$H1tkcG5G@7HX z5N^%H4^qvJqLis9xoo_SB}+U~YOm1T4xdxHXgt{18SxY1j=Et*vfHuj5clU`^b?ov z*97~zlq&8-k*^_bjY)1qZP%GayIvv`d5(XU*RK}n2X!^<-u&t{7jbg|+b0UB&PD0; zD%T3l)UTzNW5r)=!WzqlEJ@C-7fQv|PJQCB!SCl|RF4z(Nc6k!vSD_e&#t*w99J$b z1P`Alc#lBUVejTjOm|crfBlR=x{6!tL1SHjBFrFk3Y_qf{K{F%11}xX5}>om0^Hy^ zw+)TaNKW?g_Eavgx!FMfnG;CJnxkH8mkkuej!BL5?HT8{1N(F;TW5wrZP_3Y6r(WZy>=s9^Wnu5eJ}HOUh;t7X}Gp`PQFP6%_Z zem%I-an5ig`ls!5ie>-F@C&GgaA;Mmb`zJb~K>=gho( z;Gd&{0V+QZJm`p4lD;P8Hq6lHxdSCZ48UeMB~#L6jW&lUI4}4e)kdAmD3uFxmOCLd zaVqEY&ZCwscjJ>ToP%UW5u^FJfVVV*`*a@VXsfh8=Lj*D3jm+a%X!nuG8v$+R{#R1 z0F3C!0RN&01TXUJ*R2&3*?8l2>w-V(Wt~$xkuI}Day)$woW>AJZvDRNM|*pXcILzD z8t6X91qU;%803#I->XK@pBLeZ2%nxn0LrJkj^xWB&_n+v*)II@e1O$?#%wsFZWJd& ziapnAuyWFzUtD$mLe-e^&bFAUhZZP7=-K zjklP>N~`F-6Q_OL18?>lFn=;<@C0^LiRS_j!&6mu?^tnj>N5Ci$Ajfk4CI zaG5b2(>jn~w}H%D0j{_eF?sVtm@u> zV#7NUV{xqJ1?R`xx#SX%bY#^MX1NXw({{e;uI<)1J%YrSxi3;qINe~fh4>KW>s- zu~IRJnDIidR3j>5S+OCved#ycG9_wWYyVm?XbEcUb%5A$5Uc!l7z4+?5 zd-^WXh3=rOTkRDH+eSs@0tk^?TXJXOA@^8Mqz$^knxyv`t#nltCAcOGL<6`G-;QNo zbs4XTOfFB^J5>CP?N4CkWv*F%tN~%!);saAK%t@Djon}2m@@ihI*yOs*I#Y**q7*F zauc96qG-_y>yIH$Tg9;SclV+77XVOgo4E#@`9=q;y+*A*&q~Y&Qw25wqz`_wwSLgg zqiDU_6Uy1*jiqQmV;gNwIr4+u10Y5TNigjJ|b=k7Q0 zL2o23Fn|^9x_ASyTVs`1X~En%i%U!L-|szGjz^5-Qk(&XdgyK#-(Z>C7x8~}f&GrG z7Ve*GD;7+AMknjTNoHfch5~vZE_hAqktw*`P@{awy1y9K+o%E1I)!s};pJG^=;YqF z!Fz&qoCyzFy^cxj?ZI*ijCnVeT+JDULcg6s70-;Hor2ch!fY{C=gs)h{Gb-|m+SJe z#r(7_mhXIUxgnbUtYc=(7BFDod)D^;Duw||=eYqfw~LZG;93M8R&?@C_p9$2V$lkX zSI2Rnxm&g^DOVvsY~>JQw_LvpF&^f*xg;~h;yz7IU(js=DvYb6Om6UDG}uWbYES~j z1DC~cs8tTd{g$HSMz_l{nEXHq{a2&g?{LZ@Wh(iDmD>oS;wg5J-sZXnw^lQY2r1hV ztp;E+PBX7rj%@&+n^Sn3*(E8!3oZ&k4L9n>8U&^mfcR#6b0+x1`mX$U*Lw`%$8*>CP8z=+GJ(WN^nqq_YP zI?3P50f~+qLOtEcOp4MS_S8vtX9^wTD|H%fPxIx70HiKwQjlwzjWV<8x6av!qQ=p(hee{n-Bg1~j}#Nk(w@(LkA?o#oA)~oQtJq3m5HR(=!HPU$5LyB zWLPCQpeFo@NPejDMVqGG6>NGnu7o-tN__E);n)<3EwSn?u7r%crjdrbiDdF>Kexel zU}fG^r@lI3z1s1l#-&wJ5pResRLb@P!yEQ=*`lV(SdFKIf;_&T_iTGl7m2HLTuII` zNI08(E8)Q9VN?em7!8wXoxZA{^B^ES?Ip2m%S}i*qPO(sN z{nH@&yTdHe;!b%jov*@4;g zw&p!lE{0C&_9utN20y=T&p@vLY#+i@Cp};&7sW|y7)XoUj77yF>-Ar- zjJ1IrkKfU?XK~SMi0CfU05UEKV_sa^7~qZ(nbJ^;lovLG4ZFQvlz1je@-WD;+5cR{cz^vis+8JW!=l2>oE}uaO9QF!S3VB6C z{LO$l_l?|U%tkE6>UdjlMl6ZRZUxXuX;co$-Lt-0q-l&zRQ{(c^tTRCs%oIPACHY^ zIMtr`qlmi8*(dr1yhDr)VYs8JEdjNmf$XgDskjJ#Ap5EV?1d>^V^%$_Qo5)38H@Hl zrsKS|witx+1AogAd{R$>oxgu!t%YCV~qamSGwO-oa#=M_M4Q$gFoyQaS1lT zED6fisX-KeFF?5p+~?Wm&cB6}VvzB^YxwI_s1sEoM z2Q+Uy5mzZ^HL;{;KXfOZkGD3ar7ROe5#i6`U~*s3fxP;5zd63xfiOVjt3CUb4&heRL97GTX2wJYqeLt^tl2r@f*OCNW8aYq4t~ z2iFJzsl_|io)is=i#i?Og^p7Hn%K2@W`lL6T1tJ=Hf9U!LV(n|6rV%oak3*@-`Y?? z3m0NqT%}AsXn_T0MyJAUG-63DuHilUpk}TvuG60sn?KMczZN~x?F5gwQT@c2^Gw@>hRaeYkOu%tF#m0x$-RA!De-DBI0?a}cj`@;h_C>}1_R;Kfm6`ju>Knc!6 zubI3HI>tco|Sc zyBYR>ebQl)wN8QnbDCoE`6}{m--!B>(C2?-%W2x!f_vmAQ~1%&idzqN z*wXp|+_ydjXf$*m_~Wsm{>@lyqYDJ{yeM*GFF;^5$liiV?1dEQqsD&_TlFAcD51mz z9LFZPApp4RuI2*>*1F5pMOGZp`fKrAuMZQu9Qi->iDItrqM&v#K)<$_(A-C*0g30z7O1h6 zYqg+ifDegV2u&_elh4=yyB;PZR$9PKFT^fA%?=+#QWQW+j%R;an5o7)$3(63>LnAu zhb4^RJgvE7({;x6WM(tLem3-G4+Rrm(7#Yni+sKmq+)!#hB1J-R$5IRZ2q*+Ju`$_>z|`H75`FOIWhK;|Ca5#i_HKZNjoN(rsG*?Y+=vbL0B_^L8p8KQ@!xq|W65nv;Magg*5z-` z$@&TlT(bmnQ@j=KHMoaU$MTfrMi(kIPK<>z?j}l<(G78o>JT@%?eURXm!Nf*@jC?Z zKKOPKe>V}PIgca3A@Ez1@&*@A=5oDBm~7m9qC~(b>||#SgqVT49%IQ7T=|tmsdXOMQU6C(d~dE7ok+QqXeJ;?`m~*_t3*%c!)Bv#a~s z+Z9u9LE;}r zYb7{(KyDT@y7zP%0BtM@7-{-gzmvl6-L+nNN@|Xvkbo>tyab``Mv)+j^I5i$B?4l1 zdT#t6wkM8D0v=OkY0yuFK$o%R0{XC=?_3s;Q*csn0mH0eXzGi}0Atm0 z5c)E)h0ZPbLwx3};FJFM!Z5cPJ`Kn8rH?VGed9sUgj8TIWBy&}6G1N_4T|B(MN@i+ zb;`y^Ad}1j^J$WMsCW{UGs%u0-G+B(1~`v~<+N1>^BP1WDZ{+D!8K7NtJuB2c0GJ5 zr)xyGn}X4gpBw~1w}9d4Fq=w4STNDC&6x0 zjBHc~bp4H)oR3ZDH;@PI-Pphn`9G`21bx~aCB9i2$1`jI*c&TMhvFZ&BuLk@mg)n4 z`M+_M^)j)omPbx?wucx@qA2ouBYOV;qMvEkms|l2;2Z*LiTTy>PJdFXpwvqpkn$;_P6;{3Fs9-Gai+@e4=_{qxGq`)>-5F+riOizwy5@ zX#)i+)iCo?QOlcN?~TCEG@$8!g9|uM0jI`3PY*3RQ2{+9n+&7f>6hmt1_%6eK;)}H z3b_JfoY{};PbBO;Aevi*tGK z-579t@oEla68FN3F)xIY><%MgH9-GkpL7h^1cXT)F0s;r+zvYY9pRx~(dc*~SRl*+ zRubJ^V4(Co$U|ihAmkV7pv1jn^mN3KRV{pwkY?VIWf5tarUlk`=66f)K`%!b16bje zyNWnRfqpo-#PVhF?aaGaY#dA&befka{7m(49GnnCS*Gn50&U-Zd-fQy!>e|mG`c!? zrc|`sCSAP}@Rk=@dJot0!%$uHE>yVR-Sq*X={#LKk4ZJAWw8lINeQuoVeiNlA$picN(O1uAkJf%E1GaM-C2S>4JbeD7;PWUKo z%~_kkoOVs4<&xkTDXit1Zl4|1ra5aLDB>r~+puKQtgA7Uu9R%{{WS4AV9r;>`4|@H zC&RYyLF#%+JYPGWIzIcpEqz_X!_ky=eVT_yEuC4-OL_`uT-{Bqr&|W?g|*M;ANXFA zCU^31qg=zpFo(OAY8I>3Jqk63?%(Sh`F#rKFTUYea#)>$brlC{bqn*${6~$OwPam&jx**c@2(ZN{UYzVy4z)ZJ=U7XG&`Q&}lB{L|B`l*S>3ZG+ zOU3cWT_~i*J8P=pb)9@20_oWU`}KiAgLsc zl`X{pCLyk!%gqjyQlzA6gG)6f@YW6rjPi?9bZ;!uisQQ$L2DceR`V(gjF62xunWM| zlxO4KY~S(wz~J8R4f!h4)muVIAb};Fv0aaYrza;N1-=@E#s?(_5R^16;La z$}d^TV3$1s0kudG>?k0gEh~USqw)pkz4Rww z;7vSWr8Au3|55hVaaC?z7pRC50us_GA`+s2fHWu#64DIX}@Ku}|x3yNEZ{==6Oa2qjy?LP}{5h{;ZVxQoJd6&=Iod_&LCv%H@0a!({ z+CQl6MxdR&XCQ;J3h7y-2hvtc70?M1ho89tDrb*^>~!&{`R<3(2x{~IB&F*xWE%a| z;ZAv9j(Y2EswprEa=?QMgKJhn4b?2$+qHgNz^h2^Zi;%t{h`S8W zbkzoaw0fpu!nEX>H{H*uGsv5%=bqb-R=E_t_nv46n;-xZ-%{yD3Em z&0MJEIZ}25Hq+!!hJ_CUZHBCdG4UwV1fI=bzHzo7#L|D`PB|kZ<5!P}u#GyN{_p3{ zwlrK~F}?@t%YQ8zXxAUGfJNHr!muh4P1>VjK&*8*9ri>yIh79{HY9szCL-k8R)CW6 zkfLOIWfcP>sdA&``i!U5a3mRq##?h+!1!m}^3xpm069}%Utfpfdw3S?xms!>p=WSS z-Nru}o1+dvF$<{}&rp`T0idy~dUP(+g!>^`R!EoRN8gY6*RM>VC|swiT+1>@uczQP z7JUrRoZ1`Ci(avs-klZhhmQQbI`0R$}=smi#h~_e^fBs zCZ9kFU9tb$ng2_Gh*I9Zp?{3v&niHE^;BPI5N*jYGZhyN(%()RPZXC6x6~!E!T}8| zE*u7+st`BO0IJ1(i-qmuEKyM)>W{3QZ4|mK6@$DzyT0YHK^89#b%BQyGKl<@`n7-G zo#=aZ5kA%z8!HvchQaFX@=b~wy(ooLueSKEs2%PW2E+Tq;?B3cO5f_v z)lWCX7;C?EBzNEHroH_nhT8K|V0v4G^ajV&(Eq|br+ zk{^lt52LZp$HSb=GzR1`?^-JB%vR@H!;WK@Mjl)ijpq%y-LelrU$lM09b4yeubR`n z_o(XQNUQm>d(orzmowAyf?=T^8_aa04rj_lMJsrIY`$Z&quyFaYN0s~d08PtshFB+ z*lD`@=-hv_+biJ*V8gBMjtn6KRl5AYgACZI5R}-#Mduk)7cFrUgfQ)0qsbIP7H^F< zo{8XEU=)SU_Ghs)&o5W_kwRU!PPH%q+=>L3V zQ=50@yQeU@_FfK3@rLvE9-n9U!1P!{*0~1|?pJ?_=>NEVx`_Ope+7_!98$KuA__Oz zCzsfI!>%o6wM$>J7S^Z0_JmU58RcJ|0DoA05^Tzeh*8K53)EId%EPbm-r@<=?=t*8 zT03IM0Z68siLHP=4Ym>i&c^gt`?iovoY!*o{`e9(fG$z$(%^?DXoB%TOy;NEcE9Fn zB!Kz*kKzM3wP*gl{ZW1f?>E5paKdfbr;#rJ4faXX(a)Lo%Y-I{Eq=e67XKsPoXG3B zXpd@dSTbI{Ds;=FIi$AjvOHEG4KS^@ZJ_1l7_&|f;zPWD-;DM8lGGJ3fy5*$6=!&! z7`m)iR5@4rlka+4cQhOuf&<`v==c?pq+!!XqOTZ@w3cPQg#@yMW0S|_iy0_ zQxM8{BSjek`7EThTlognh-`4Y8v+Jf#2Wf8>&g(yEOHbG9J=j?adH|O{6zm)^yOzO zPToPmt$CA$bN6%U4(oN2B7c7|ZwTs(=~aREd2XK`-eal|QLGJ1VpfGkV&=sXqMRz> zN?~Sgcqkn4@{8BNO@SW{Awst8V5{(#lQ6}#rRPzoU)hb8Z!-Pd@)3AYUU=+aH*a$d zwcf-e{DrhKvJXF7lF_UQNYR!(0%wRU+i&MDZUdHu`tmE%-_ThCah;b_(G8Ga&*s{5-nf<+2jNV8sOac%mc<5lDRU_J%BS5>%TihHRrFav(Psh1 zYKvP7y@_rIZXO2e(IHyNcKw2q4hTWXPqT3 zoL_HVtt_WhoE~xlaBRCHdhzc!&#e&y(h?yzB~SrHV{q9|_>$!SA0o|DjTiGux z9hl$e0B$+a$kWrV1~O`m8|0c>x;EAQPGea~7#;IRx8>BpEj{Vu<9H6E7sco9-q-=_ z%$wulZb}X{(1kJRLGk<9Lr|`&>d^jEFMKGw4e4?&bZq&5#5u<7JQ*tdD&nwo=?Jdn zG8ASpa$Tl3gJ!oG5QzSk*VogVF09l7ET0Rdb1tgu`1pAsose_Ebdr!u;i?w&-y@1? zg%MdOqSTH%z)fFqa7LVF%T2lYqJKM;rMg|1M?U}itTq#w<>7EC*Lt{{$KhP+$~P1p zKLA43Jv?LJN(g_i`*D?#(M4X+;7k;|;h3s;Kt>G*9ed4Qs>9Daf!mg3H`2BRQuzf8 zI2@LT`*nDqPRnFVN=M@-+;%^BHna;)Olq(nO^>-cg{FpXMu;qPEDxRn$7oS@9Dstf zr8rlsVY`bfZe|z5x1gqU?OA`B0<3J~SqHM$IqJDB)xOtuR;oZorw;gbk;M!bW&G|b zehM*3DeJ;o7V3&Q1P(%~O62w(O3UO~{F#XBnm5gdm-6g z0-nNX17WTo7LLn}^#0-i#la=@L=^s3252zNA~joJdl;XQCq&+6in7CAbj)OiL?ioVbth4G~o zCmdBDw~B0AjtRJtdk{3yH}w|}4bmHd5i9gPITxd+JMLO*TKvtEL6dOV(^1I(zwA_e>3gBk zub)B#^MhN;**W{09;hG_rG)n1JGV#c>^sYbK5p|K35->-+VNKQ+L2EuT`A%lUKhQs zt-lwV-h=L*)dWf$z~j9l1h&snHD%=QTSr9h8y^o#;=r#1{`c!DXNre;-$8v8$8Vp3 z0I8(Axt5ei%n?9zUrrwd6XH^m1(+jS&)DmTk4W>qS;ybmWhbjwU4t_&03JM&S*QNTYLaju93VwC{d`@x znkugFo&5d7yv<)E{-53QnwfP054r@L6kNg2H*K~@Sab(K!Q2aEH`&lFW0Ck#S~ZT{ z5<2+|7-kK`mU}l>#%sr;!y+d*?^D$vhpUWc#F!c)zXo#!LETruy)1uzHU-6xPFmber2?5+e$YBE;pWraI;?pVmr>kD9E$w(vE zdkF95JQG2@wHdqWy3%otzPxgJ`0&v6WkT%t(YKWeZ+T0?hD-7MzG;1+Sz;n))4HFg z@K$3PXL6_6e6mKJp_F8>0CBh=fw#tY*W{)IHoXtQ zj~>*aqQ8pqgrw(AmoE-kU(k0zREs}&R9lYTF~mXD44Ud;D2mm_wHauuf9~ZO>z_X^ zVUP;BZzsjhhZyCoIOpdIP0G?OPV5XC3>x8Ct!~=J{j3Sc^5EVWuCGvd(^uxJ-Z5!)^f;M+k_}OE0j@P)$Cbquc23jD&xa zf2~}NRycxysJ84^nuHaIrt2HEfwx|?iSN=nXU0}fPGz)+1#9L*VBD0By1>O`a0gk_ zqHF?^5^QjmSRWYixP=jD=pkQNA}V}{NcHrJ&6MB!xNOG+hn3K5ZJv8^MU)Gy1{+`8 zLuDyG5#$BxGA!c+qJraO8dk_TtZHz@FLiDaB-xK8oNNzylaq=`BsNJF{lA{BCSRw- zBHL=PpnYhvDcEW~%IQL9qCo`Fq-ok~x$OVrBX!=G!4VMzB?A?-(k}UHKNrrkz=KTw zcNeI%xH?RKA&g{IXGKO>U?H&vdR4~Qe`beuu7T#but|9=_se4#wSo2VA6rMIr4p4r zfrwm*c?uQ79NuT9xQT0p+=Q+Yt-e=SQ04DGWgwxQJ-&5EOy+3npMSE_*I>KYyq9&# zE2aOZ>8{oG%IJ4eDVI-weMl;R_6}B{r``c1#!NnqULVBdv|nF$5_$JhQQ702kjv&! z&63(r;#hw$cMLfH&vnwE55G-Qv8=9Byiz8Ua4q3LGyGlFU_fWhrr6l84IyDH>_zaB zqAZkUj#o;Gd8{*WKoyLzv|N{dJ}c`UlKF^tU;gt zUW|6Z&p*{o-)$#>Y(o*Y;`(i(1vH);Phx!+W(Y5m8|9|{BQjwRG$?(F7F#gxGKWh+IuDL04*n#7c z`T8Adbu9m}<#HpWD<)Ey4at(+=X|SrTa;0ovg98-`rki!Oza|Ry=?!zUO^iU|6M4m zFKi{^uuxa2|KET4|2nhqw*LSA;;QE_RO(PCdcyV}C)$(*Vxkc7%+h4hYE^`j4!>Lg zFNemWHk|AK{&v43l}Tv45ksFL#@7D-Z0xuCa|cSH}u%?)s#FX>}~Slr)qpr;yJ{+^PF}1{Kh#KZ=sfW z#!BXm#$MykUt&v(iD!Z@q?$YFd=ad^4}u=Czjm|4#n*1VPX{dcqKrdknULiB0XHV_rpkrjWux+hz;aC{1O<#)zu7?60l5>-WU#9At z~I3b>cQ|nc)$ZMbC*4PcY#~J7wkFP4mJ4>Gua&;_`IIwzfoAn7P zr|of-+6HZC{QXq3@Ko3j&Y{BQiqIP&)0}(H`&w(9r(`)jw+VHf#jsrx`0qJ#K5jzO zrIvJg_rh#AfpkNW{TcT9@BN&F^I)-It%v@5y>b=3@~4vF zPe~yTO~y(D61A@iJ8w8tzg)=|TP=0_PRqOO?yqoZhE=1)S2c?FLT3nSLu0#Sl2pPb zJWDZQ)LZkolXiQm*l}4$xJ4TRXyD_QOiCXg*T>_P$|1xqxJGM!7?OEE>Z(p-5?M-W zRT+?!$wro6W1vuVf5%~6w$j?TKQH*rK)X($-P~3!QFQZj2{RmbCDw^ZVL+3^_zB8xYBTvG1_Vbdz*`^o&ccNfGYaK{y~p zU$9W2m0I=<+rF>w(n+a$&m|SSx1TgkkvR!ueRjc}6+v4Rw*uw03t6T{Co1c%=!T6< zF3h#?$@9zG*ve3rxa(xnHc0foNs!12GV9tPzU1Trq zUDo%s(28%m{Y%%y^T+SO>kD&PM)1L#TWgzt6cv;Z;q*-s^Wv&w%#zuDBHPe2dD{%V&}CV&j(Ab-pbh@?b+Rn zA1XGibW|8cLYaEQ+U2-q#kS&FESD$oSEz<8=X$~Hse0LT#>CS zZq>ci(0n?J^|r#cGGdqY;9^2fSQ3lA2C?gg_D7FX2kE#IhDTWg$J_^+4!FIEx6}*b zkk)DIZzk5iY)*ew9js?*q4Iq!#rqC*D-;n|_&A68sVL2(Hj-4_hz0miXo?an50|K( zroO~s@YwmOy$;AsP60~AxQ3E3(h+-;-q6X~L*XWn5C#MK5d@7}{z<2wgY>9EKqW&y zyW@E=9wqmEDe4#nL3z;=KMLO7YFDR7P?Fm1uIQW2*Pa|$MzU$&isUqrioB*kxeirY zAmoVTU(J8*IYuQHyY7mqQn?DI^Sxn-4#G$4R~RL>E9ipyD{lri%D$8+kI-#y)0V8x zu<9S@Se{SdMY@8`eqvE(!UoAiY(!{F;TpU!nnC>f<(<1)M!I~sE}^?`gI^1F z1jCgRm|ubSF}?0+TOd>?yVhvfXrq07%y>9*ZpI+j7Kx*^wjm`nlI> zIk5Q%@Gr|}9K+9kMm_-q@0vxXXDw!ef*{E_4tCo7e!L7XPde7H`4 z?MT9WIO;j>J4zx3MV13M-5WQm^IJnQ0hd@-Z^S9LHjT9D z@LZlyRu3*M&$#2LkJ<-}q<~VI!~b=hNXvbkedf|y{(hp-s;&{h3K&?kA=QRf>CicQ zD=+?^K!_$rDSr@nen^u+1k{rfZ`ib{7jWO))X(Wz9x3mAG>kUe4)QvEo(m7g1pFG& zxiK!^@M~DwMK@Bcf_QP2p83s9_l)ZZMqzs28$(a0TQX;JrpPmB?7!L1-MEanNX=e> zPo6t@PuQ^IBSMHY`(7M(Y}VQ%JWgh}y!o|Jr7PmiZK+%LNT|(IZ!KRhJp-R5wwC38~S&M?Lu9{pFcCeLWD|A0FUJ-7COf;`Ni;wb)fmEH_Wul zzrC$ceK8nN7h#=kw`0&nzTpPQi$wO}%mLUVD97!fl+V6P996WZl$#T1q(!}RRShHf z084I<;J`~E@*!qXO`sNB!q=4)PU-u2c;7U2;AhSIFr#6vhb>nSM|_IJE|cawY&Bnz zhWzr?Dc!vTS^P^JTS`&Ripvew2H14EU)={Qik1=N8sSUTs=0wTZqoZyNqPIwDk_iV z{FSw|>Omrc781~0Z1Q>sxK&wW_HC+|9E+&gRLp8w5oMmIHI!obs$q%t-ax?4q0I(s z2-czmdT|Vx4u*$}aCt)KPcjRt!pyLDx0cBAR=X+kjrHL0jY4VNTYToG{EU1Q{LHX=;F2LlW8&{_dr3)sgBJA zh`YUtGGdWJ+Cfo|k?jV%_w(Poik&z$-k*3b#CunL6_luAMHS8{R6-62KQW& z*0dK;!SG7$l8^JtCn_^g#Rd3BT>C_cs0*hNyapnH$Aw73%ecA~Mjd>JK2BnN%5C$4EP{tnJM+Ndlp0+q!L ztskI4MSbjN zLyt*RQ)S89AP}JBPC>BEY7W~z%+GzMAhMEN&(t<*CWz@sBtsHE9EmK7UL|9%)zSX& z>czl=(KmC39t!fh#SQCmM4eTa#Z)p$EO+%j##>I+=~_H*cq|uPqR&L&d(`_otjU|Q z(PJwpW@n=|h&L)V3Rs#}i059Yqg?fTCZAuX+OgoRBoGA3{2-Uyi{B@Y)H~vKAVJEe zL9bcj)xjm_SGC&oU+b)0$?Q=uEYyu%#b_7#R7G1o&#|X9auJC$aD3y|<97Oiei8PX+cFLo3!-$QQ2rg9W}ys1f7{z3Cc_Ta(*kF=z(Tz}Im zB~kV_)*@EHyN{b5(O3K|-w^1b$`H1H^YhJz<2P2q*CD1|Gho~GV|f2CJ35Mf-1bKX z!+X_mqs8r%SJBy16$-;yQ-qh^XszG~Z_T@SZYJ#ZbNY2;%9Fg;*y7D>aP-Pn@eP1L zrCX1#{^cGj45?1Oy6JAG?4xY$R#gp&lf(XgPAf47v370<9 z{!B-NiXLp~e(zek6Ja!rL*m|2+WwZ_-lp7W__}89V?i>%Y!mWIyCbXBB+y4qk@DBe zi5wPwN%-VN`7Lb9Eu4hZWkb|jkZemWn@kc?d>W)pwXPBmF5A#EIhuFfXT)d6^Ts~! z4BsKy(EXjDagn`;ATQ*TY`*IRoxIDccP!+fM9h2Go_KGIhWKW4rydLGd+hj>v2db| zvo0^H?$Xu~7}xQeU^!lH8Jbvkpe!kDs&gY_*B-VD8MA5A&sTYuA|NGV^5qDbeVqKJk00mbyWgJn zTz}p7vD;FqySOs-%hMMGO3(eA#IOjsmuaWA`t2t-+H(;Fl_};-V{MmIhPFRD*Z&Q` zFcFZ9XB^M5w5lJ}G-L!;?c)T_wW<|2lDQW~={)NYS{)_OSnqs!Ba;!gm%K|i{Phf{ zT1~moH$$>7zd?dou_)LS{-{6oZtDkS>Sik1Uw=yOQg-fL!rX>y=Kw7H4J|y++5>Uf zd1*e4IOGyX+9-86&v}9|h+g;jGy=mH1qP8c)!SMhXlI2ZGH**T{z71O4GHC-bT+|y zW$wARmcj?VL|<3=k=~g2jnIf}{Gj`3iy1SZ(rv$x_9u^C^|7e1jNRIJZDWPWcQtmG zXF^e@$1XbsgU{SD%j|YD7*|djFee*ldgVHC-(M3+=pD6l+wq*cVUD+xB*3up{POoUdpLo560Y3Y~ms6 z7bl$wMQHXG+;aC@cSdOjIQ%N8>L)$5N<{5mUbRRmXRp8|?ziwvMs$DVGf>N|7u_{> zaS$PQ6295>8^Dq`Wv0jes+|2EE-bWQZU&aA zs{+tZ`W!q?kDa6`IiPQ+oF+qPcYNS*k8iNTA$Jd`@u~d~&$pr*<7#i7yhGF`&1()3 zdF&mHry83vL{@(fo?IWx&-SEJ+VA0LzW5-|aBo4F1fOKD<^|Swj&{P+)$QOgK7AWM z9-ai*fa=HifrSl=0+XA&2=x#x-mfn)LWa5Zrx&yp*+i=hqUKLa8IF6rJuk;)BsgDE zl1q45K|`!ep=TBvrul^AFNE)`^3E;d&;a^HC(fxm(>{DFFIh9l?!n8;o+?@0@r z0$(PU1`(Hyhp0N|BaE7iWH%Hs-NU=}sEt`nOiTiZK}`|#;%eb;Fnd_S8v~Ep{7$;u zYYC_qZx~^$8x8XwRg1fEY+sKoI&5uuhJS4Gg7IW|4PUZfxxFdam9OuYS)B4hKl31-xVYkW<@?m}(@eN=NeTuG09& zWjBf>!mQZ?hg{$2^wbwmQFdNLXv&X?7>1tHa(`B2m(RW2sQYhus3~N?IF)*nfalU}+FZh+YbhxvvZNWT< zOBwMf&vFc`KpMYDo^cHN$d76Jpe~JygJDjeu{Ibb*za;pF+M8{WrF;4`b&!6cj@zfKVbyeEgk)GqHZc$s^PYk zJX}FUn~BcX<1z2U$>;Bxkmv98JbPYVI?RWvGvDCrK%%%aJITKW!A+K&AfWE8U!y-`J!j8CgH*S8905 z7C*oeY}>PBpkm!TSr4&k%6a#eEra~Q7eT*V|GcDBzh)CG#B1etu$U2Ev^g4?t|b$G z5hL&VonN@|dc)E}-Q*meYCnMsZZt1cX(DHF4+OIFB9RxCm&0bmwH?utb9RUhA3uXgbj#YgBujn znkW}8bLYRi?;o9)h`o&a1e#$?jbRYCI5DZEfPm9xk-iIM7pr)fSwnHY?xz&lw;5;7 zc%6}zxT~g^CKD+(-I1WH_FhXl9Y$`4H5I>eLfN~ujG#&{3g@lFa0;&G$ZG<<7a@SD zIw-toKd3_lNrQ8F7wk(&baS=!t*Tca zjE$LElpI9+_i5NqCsC=5_7sH~9Xh)=MTV;7it@3Y=>VOD>c^dl#y}0qc}(kC z^0wS@IWCSaeDi^*qx)eAi)sen?58F91Oas(T)ir1_WH7GyShq?L-R zn$0>%ryg6A*d@G&Kfvj2_L6d~ruQ<_sakFa{-H^#K&|!4Y57wrAFKEbzg82fPg#7= zPGTy;vk*Ve!y97Ll9`R~3r6^0qMDQp7(k%)5yg4XPyysI0`t5;Ws#v{XaHFT8Nqksy$3xZ4PvrTFOZeNH>IAmLJsaf*p83Q}Bn}qD!BEUnf*& zo4v0RxQ&Hx4DINDx3(IYgwukSp8K4`?I|;2EHmkz_vsTIyByfnFq!%V14Gx@YpJZj zbJh=IahybK!}MA$(Q1srg{I?3BU1aC;(Xf&Xrc z{m5k;arY>>!DD zh82Q7&4Z8SzAEDIQzIV_x^X<8bGpK@`1bsAAYN zYx`F35`M2L58+nWtdsI?6!ceo}dCe}Ig+y5?B{ztbs5Pw*f zq#LScK8ZAQQ8)xyw{psFdF{JavsN74mLXm_tY|9s6q?fQc53Q0?poyhm9iGI<7G46 zrWs$5LC+g6XQ_!9mnQzHe>a__FEe$%!nvRfGJXcUStHNepE3vC54;v$kJXJwD+V3B z8V(#0Zpk`i=TFYT`p(z>GGnE&Q(~cxM@?jUL0RM2YTnbyTB}EK__mS|S3#Tr*+$x7 zPs$|3{WshnO{WjOF51_X8_=rg@=(r$z-?vw(DwCe^Rd!MPlzelCjj6`)c75cd{>aeD_JWK>%GHn)nYPix%Cf^Bi40?}s)UNe zDwxax*pJs!HLE)}A}8m4rxx`X4{EKrmd$YQo-okvho3)h|IAgEZSYflBt{Z_ zNM)@1Tv(R9KVKPto$|Jk?YFla{5wyV zIc(=YNU|4N4;wvdXB+vXLQ&1oBSEP~-hC(5gR97qU0Jw80Q2rj$r<-(6&SF!o z+h$H8Tis{YpS3^rvJl_fg?N&Ky3wuZGbYx_weSD*=e5E(hKu~QUAQHKWO|b5eTFk_ zA>+5c1Du~!aTgPh$umVn6rH=`hr@TJlLf2>tTVl?P>**Iu$2fi8}q$w{jv&$#ka?@ zzDsu2&41kRsN-0uQg!ALv7fedQt!py0q2(J3}UhEwuYl+zLHKt(wcQLR5daADpvm- z<++ZN)v5&&W&8DJ({7otTw+DQ$N;fgX8pb|Jvw72Cu?yd$m)(r(q1fon%Yu*P` zb4U(^n`0!*$}4-(Kk`^E^czFGWZd>@+Bd}{5#e&$xkrBt2n0@Cw*oeYumkVJ6`eOc z8P<%V&_QxoUYs-@ZWk_nuq5i*$KiroDebnrZq;|+ii;zt_2LKB>J4&{@QHnLxp4l0 z#I&Xmn?6@$l?SekG{afM@RY@{Ce3KtnCnbIMho{+J;Cna3l?0yXcudNE(KI9eO*3~ zf4=`^(sK&jPsk(Z>D`Tnr6!Z{XkPrHOmil?^vXURmQUnAySlpKdJ0a3A*c6=X?^s^ zxKZ|Y&ijhg8lhMkzphuJ7Ot;<;O(gpb7TRcZRs}EYW3rb*^<3&4Mm>E_T`JCNMjqi zlZ}!%x>Y>#>M4$qM;x8Pc^Su_Yo+_kJp>DM!k=Cs|0&Wce#5B3JgH(z(}DVJH(tzz zHHq35i^a3Ev!C7$v{EbdDo%=7Wt-f!)?vFQBy_}LKG-SSa1ugGri5Zq{hMe(z zTtSA=#i-?40ct9ZSIDy#089*68*1i@i+fSva{90Hd}f{3`mx;CUzDNNZNI&9s>Z(Y z#&c(0ne;Z)r$@z(RXTMd0tNS}N&R$-Jzvw#%+naUJbcH1dws-2@;D6VAXY`nYk!fW zSJ~>r&ixbrrm?XLHW`Q(yn=wy>E%rYmQ(cL&v=o$Hi|Y~78;s7PtjbAy!_4;nTw(d z+BNs{qh7g@_z3ZH^BF#U91N-m{DMnpXgonC<(iZ*_A# z=f>jlnm`&qV?WwTy!B;17FiyFoK>I2YYETFU$OeO(u9bjth--jXu5v%BW_V=HPrG0 zqNP29rfsZ9jVC_&;~C-2FP>EcNxbqr2{+ENmHBsKT;I2Z^D`KszgVV*2hlH0TZxpE zv{dEfu$q>v^UrU0<)P~RMr&>#g3DJF1QEVQ&x|kx*(oohK&<8`iAGOO)9(o3ro_I| z>|izVm>sTtv)0b!n9D!GM|a|`hQI&r^L}>$f%g=<}?$^^yyh3hUME)Sk3s*CL@?*V@C=osh)L z>%BWBN;(^SVVbv1w8QrhIp=dEZQ@N~qVAE_Am%;mcaG-$op8bnl-$eH%4re9m$yS{ zC)iR_QX0~YlE5+PQzJr8=+8-7*{dga32{b<#JmEayI=-OCH;K$i<)qkcAEC7mc{CP z_q*PCJM3TdwqI4_|BByMIlf4!$5DUvk{$w=_W{S;6s^8u59Xbn0B zL_FNfR|Rt9ju~Fx3%B)y#@5WMN5{q7D05#J|LSBRPGx2 zFqo;BQHXW8)GD_J^bBg@g|_RHpp_Fl-wiSo;T9>qyj8p-m_jrOlwCxD^iZ++E83{! zCu3FG_(9jXmun=cvPa>1YzHD{q*BYRpL)*DWxORB-~W6)p1WQDaF|ZSjTtpn24oA@ zz+A&}x-W%Kwl#~ z{KD=SAj4*7cbhYzgcP?P5&&rE6sheS$Fn ziLq%$qLff*D1~qSx#Gm4e;&#ay93Sq02EySCAB+i59*3*>|1m|(704$(O>9813LL? zNAM0>EJ0bHGLE%DgOz<_u9F=BxG~@yS5Tk^lieB!ih_Z1698aN0LWh#x-V`mu^WW= zE?v4e(=#DKK1y|0a``;oyem1Ce%86(D;XK&Wqhoxj@|%av)?pY!@F&N0$5zxoRhIeUiRTsyf<|wgu*95JYx)l15#}#>Mf=} zOVhbe2LMnKKi`uc>^v398%5|x-*k9}oYWB293BG!EHefk<+L+RPan)7sm_2B)fnjg zVP*3ulT|g^RJ3HkUKUHh;;f_$v7N&>3gdJnKsBO%gyP5pFJUsEA;1sDY{@_DOw@M+ zHRL4x+6+x8TVV2#d;&0W+rt*XGso;Q&<5x5#UBDjN(k-Uk5xNwZE8NccYyer7$r46 z_zs+KYW_Z#E1$YAfgVIvP0z$xCDW^a9j zy1rtNU1}I0WTvSK7GDNG^>T%@AC%lyLfZ(Khjdlt9!NYTTrfzh1)+d{qz&FK0 z;O+f=Kew~Z+eRaH$2ep+vsli70H6$E!?AQ9H1CpNtU(jXx)=5%k<%D`0Q^$E(oa3a<~kz#AMUN81}w!|=O=qwZRo8*T!wa4FHUVLzue@mX~bJk=@43o_)nC4rI2_ekz zP~%6G!Cgo-2PdqGT7X=iQk(j;9$}3ZR3^bNd7qFiI=S?kkL4*S&iew;<(KlL6_aP z{>~3c1t9L&qX+MeV%mND{dH?Dh2L7fLkF6n@NO!zX^zjkM4@zFT+j68xqI>nja5=G zmt1A8uc`!uz%;$1<>`fn?y(1%`$`s$~lzEoa1@eu%Om$Aera2o;>ExE|$LQ^)OiS^W{E^Fcq z=k6G;{1Pb6Ot2f`UG?ay*H+F6PnnI}Vc!9&*0vcH`L%HM9iwmERHL743`z1}ei;tZ z>}s9aIq?`$uQg!aWG6m;f7|AZ*@L=6WWaeY6J(frzIXR+$_I#@pXU6$h)qIk+*jcr zpx5!K4vv3%J*Yyg`*lqPzZgEVIlIm6$3Zvp zLm6fjoA@z&polTT%?(rJjCFq!?6*J5kxtIz#lJ8+_MnQiVU^3YC2a*w{FBi}q=-PT zh~1=w1Ma2VaU36)Y4RRx4;#NaFrH>U$JPA84FG6@T$rHgX_9dExT*^r1^O(FEr&Vh z#?R;$(?4maZ0&e{Ve2JT@Fu^>@H!$yq-&Mz);D}FbN_N)=z1qa;RR_q=M_Ns0K$zt zWBY+)wj&~*3{|Hmz7iC{f4~1c`;L~0WcWMg7KaJ`ez>9H(*pXIP&br6H@_vvF8Ss_ zx3|?ww;uQiEm9ySO@Dyh#^PYru;A=xld=s6yHA8u=h1xkZ!_yx6r(!pRtq61edMY5 zU9Q0?(^?~nO2PDF91BwHTpESQZ7_&7yBEClF7r0)$VUR26|~KK&U~6Bv>zU5l;^sr z!sQYGR~GNH8xKIQFh|z%Nv$e8yL{Td+8J|kjk!0BesS-6)ta7K?tU2n8dZe!1f9r4=SVB-D6jrwzei85E) zCFBc>3jRiFd-t#+G=vIg<1vi1vgr6&6@P19fTNhh45rJdA!C9sdQE$JXhD;F?eRLzB%-pK(2#avY&IzQf=wX z0~x^(D>WA*c=U_tp<^d7`ar8E+3xK16)L>*SEHTp<Rqh*9F9c)eqxE`s23PVN@t#aFaS%27-8_Bmu}z^?21a)G1NfCzE` zUMf1w=B`DslFe#rF1S^R#>y7peK+L7me^-*6Rl4lQ(d0vmZnIP&b|2Rjm=FZMAK&2 z8O@%gRgG{689=%@>(xR$MyOStH3^G6yGJHG8G{~{vOvBV+SGrBbXeR*=o=mf>7h6x zgwkxhrkb+Qn%e-tOFC0v9hNb$7evr@gc==a-8*A{ir2Ln8cB?D_KoApzx3K1Q_J$q zDjA;8{PX&=PJFx?b-eS#CAo6myWuT2DG_TFaSDQdom2y-kkR%B9hp7(OzIIM;t7#Qv-o7w6|9NqhBZ0%XIrX9P z^NC45GF-Y7-=WZpTZ(Ucn`aNOv1f}JYB>ffWFoJ$v>9{qaXXU>FQ2(SXTrxf=8cBP z;(U5$v(#u_I)pq$#5?A*OM7qw8h6%@s#)Rok2%7W;TtVj zD$ie)c!u`(Wj2YGF;6%t`d8WHO4`OFO0TXEZuL8b-M&gYa=70b_g|>Un_=h(*OPY?)K7Z)l=Sp{KXy%C);@98;Asl zdIT8W-}TmiytU>-T+=)Fa%X=oNfW2hn2F*ixli_G#IO&+U%%wsy?qN4QTmf`ZY%9` zfjF|;LRTAQuSvJukZCw6ImXo;Kd{psxkS3z-+RqxEq?Kr z+D=rgs~AZF1?a`D$}j`Rt25?pkd_7sK{^+yG`MJxE@|m+%;nzudCz&T^L+cSeR=IQnfDy` z==hE2qTg_kU>QS17|o6<>#Aoxz91*;G`RH(CItMUH%2qZTE`RIX9aWoQV1vRKVEWr zlOtPj|Li0{UpX|i|^~(>kh|-LrfQ~4W_?+ z80tUog?)Ca%8H>h`X>F3Z$OhuW=5ySu1pBG6eO0c`e8&Ww6V{$k;5wz|i;`Va=NaXc zE)=`>ejCrJ6jP@|JcAJM^|P*P5Tzd|cfGU2z4H^mEUyA!)|EFN9*tbp2T652QWXH6 zm;~4}&}>3y)7aG$tWUWO@fN$XIUsIpJ#PuW$A>#k`7#D3ef*I29Xj6om&6ucZ8XYoySIcJH(cNQ5R{W&JAcgCPF44oYju;>p2-_gf0xMV8dUcG*w7e>meo4rcmh z+0@2w$O1$u_J9zm$fb!wXw+&{|7r3IHTG~Pg|-VL%pj+9*A`8Q%nT$MI>8VadC%y_ z+ozw$bj(}D0|>>Z>aN;{U?aB#syqN`t#E`C(g)%hHkIHeEC`1zPC3AC;*uhR9F0Or z1g|fML^_<=&j@xUpOt#xj(~g`ouWm+#%-4d6%T_dZo9S#;slCNmu%Xg?v)zCSSXBf zKJb<930Bjgb%R9_ojePr>$UDJFlg*{WT18h|Ni#>2$oe0O?zdP_uvDOrXF(P&F83?HB-zrBLMg9gL;A|!dy7wrSAIZW843Gm8C7IX zP|Fv>Y$I2EmM^pjce4tE*EZphK|PL9)1*Y@66BTZ>gxk!>fIC;utdKR{cUk@x=a~EYJX3oAbD%Lx-6BK>Fmt z$C}9GmsEFF5XebBf@;voY*hfMmWiUtnfqM;_7REyaF3 zxTYV-@FM%Cf1=^VYfy8oF+B$(;#{f|HHSL4Y2t7yPhWvXVNGN9Vr90wkl6*eh-aY& zhYyX6jPymnJ@|)0axGvD%)yMwj;)`28-QZr8EBRCE3G-+m<)UlRa2bxTkt`1D$W&u$htL8>5@=n22GAsVzlS_cuSr02Xv1iD2^n)E#ud&cC0n8m^Kk9uIN%`IJ`WUSL)FWNW`N%u~51t~1P&Li(f&syBBAkfsk&uheg{QGJ+F z=W8fp1n7=#35p|4)fmTzTmCD+DaD-WvDo}t&PHJ9vnF79IAi%IcoBIcq%;jKsqfoM z@h{dA@#|?ct^ShsyjamQ0!{mAvc!5Iy881D&eHOUw}CCoHJ>L2c$C^ z%MPh9G1c&zW1NU%cR?}5y++9u?&VKkbhaGiDi<0Ot{C^bD=%@>+*)^72Yx2*nF+;D8Rp&XC zbZiVHpGq4MX&Al8)X1{F=V6B27!zeHKqo|0uBwf%6QBOJ4aq7?e1`g-nue3Qx5& z*q!%MWF~#~%t01g4x7@+hUgPl81TOXq;Oun9>+}7d;y8bH^1G@6C3@I-kS79(c0>> z^Pi@4q5L)Gwl7atK2$X2s>h|e*@QYFFYI{1Bh?MxpL_KhFI0myVV3B|jZJe<4gYwW zkdp7K&=-wMy1Ik=k3>R03aY}wtjzo76d+QO0LG9~&hQ|~IfE)_8YUdbjI|?BM7i(~ zxO+~(;+Cq%=bN~fp=C_DazI_v0^sdT*4}}0lGUeOpu}Dy!9iK)%{gYpWh7GbvLKU9 z%@Xy{X|pN$b&Y!5w~;i_%;gnWUGt&gu1&_F()=bwHNtjgvc`h~_gzy_yF7nWvS#xV zM|0}`h)nc!GE@kmBWtn|j4&bh1=@|O&ilbvaV4quWA$kGPiH&%$6KA=OwtJ!@-EWP zB5P+vfK&TMGq5SC{Z!Sg6;kR=mbh23=R{HDJcHQNkd9^}z@O4xb*RAJ81H&wIqH@J z{)$O~5JcRleeRlJL7QZc0I1&0Ib6P~H&G@5wi^OD1#pEw)33}TWzN~3!QVXqrfTw$ zg979TLn(1RGweKnQ$V3cCL7pAF--ibp6M6=$E7{eg`>Ak@STQ0>`;G;o%(RkV1jUH zF)R~!5|i#(*;SDFl|DYSPP!aS>5saR9O#YAP<-X&;DXn4MB+p!iV15FU4i?4yA=9| zZI$jXN1G%|3El_a{0S5Y35bZk=b*4o{6j^;%h1tS;Dr<3Y4p0XV$13QUe83nejvPM zp(j1$J$1TI`4bqNeAu(S`RjKlvR$jU%5zkU5W^cJSbnK*5XmRHXoQ|RD=*CB!BA7C zln8_fq~uA$Rr4o0cg|HN1poZs@tQS2itvrd5ba1o$DSmI#^<~9;NY?mh*okpBWZW# zihQzn#KH9AP$Ft*{i!Sa16nN`z}KbIg|TWBxDPYMl!m=Z1yvwRCOozQH?-{89_*LP6Xj?ezp0uay$vv}(MoC|AG%RrW0e#Isbn9OfGYiG&RT{o;Jtg1=6 z*!8R}TE23o07Xywyfso$k|dx-FH0?sXz}~_OTc+6d;G8jHg#QsEnp@S>Qiwr+(`~= z2IC*wV<%(fW0}D$b+1|hL>j924b)BLK(~d*O{M^7l|H#vRUk?D4Z2F{qqqbgH3d@j zm4%Tf6I%r;o@nN}!J!k0J&Ax@N8yyd1r$*Yq@i}}Bh3I6pw&so^5=YYA7&`YZ**?V z#WLc!EvEBC!={QFmQlt(=EX6c9jA483Ou4p&-gvRpYWT{_jB_JuG<>K)YJ+xHuBi+NE`Egl`gnL3 z0i&aaD2`szmq(UPzQT}BQwOygSF7|WD!6Qn) z1gK91Vx8#93c%7I$kWaXE{MtI5utA)H=q)o6@(#;ljY)dl2Hhp=K=+`DHSiDg8$Kx}_wsl$VoIWWPzBiy z(6Xj|5GSa}r!c-}bfR_)+1lw}Z+KEa$Qz3``SvAf2;*LEX0Nc^^qk_o>!v?T(~#_Q zjD&o!m?lUl_*>D`DpKPyY?^zHQn+apS>rnC09C9^>oZJ*I_NO+-H^>Cfa^IwY4Hc@ z#I0sSX%@^e7<2a5hxK)J(XFkOPqyuMbpO^8ue($SB~(C3)Q*F_k$opbsh>>o!wkCH z!tz9&HXqJkq*V9Ry?RrQE0C!O!iVQ7L0Uf{(fWyTt!Yc====_3AhYx-We=JrR}mz% zEvI_3$@umiWB%nqzf{2R4R(Ir89S09LrO-}Bc@w-24&h68~F5D;1m)ljyiAbcGMkC z9d&+uHDcTu5M)(oEX5`46bpM4=1XzR#PK}>9AfNZOsC>vgo6*>v`C88*~YFi)KBo7 zJ!uS`F^-l$IX!ic1-aI11O@DBG8B`&r$s+1o^lMR)(4z)>DOIk4h&7M6NeM7dY?q( zgsE}bdrriWQvkdX;0wYgRE&aNgcJ&)d9Y?!W+ zj=b7+$6iH`b?2&Yny6ZxJ^7th2r@Wf;|&(z;o(1*h5_X{V#%sH4t}G~noI4+s8F+* zht1rXF^@(7q=_$uF7F=EH3F7N9YJJiK_746BF#qH8kbY7brm>}858r8s|7!b>OYdh zDiAv^$``>7G1~x@dvnwjs&0)?wV*=*_(M>4(bOKLTClT(M?KUUGpTXF-2{!OHoxi2 zEy-3>q;K)n+9G-4^hS$rYuKYbQ{k5jDcz7OCa>mQC$FKT?R_4W?%mVt zxbF2u^)58l+*6A0>?+(3f)t7ODkp?b^u#ks5w^XIBd&73D$oHSUW%R9n}fEAPyMJ#poQ%uSPHE=~?ntYIw4=#f#qRsx6>51}IY-{c0+v50p7aDOp5#s~ zEg|-%cd3_)l@~6luXn!A^{d2r#{#t<+)|{kRi*psobI#NVd4c;^p^a~kh)j3>FzM* zb{{Q$RB;R_UBZ){J(e+c?fNKJs`@D?r)PVw(-^OnjoUOmbg_SD7x@;{{MU4{R7lVO z8X2B?nyh^1=?~8#hjDXy!|D%mwZ+$^+NZv)P0ABzIlY z8wZ|uc5%dXq`s+JV8(Jcaj~iChR5p&H{a@VjTu*H7iR826YF*nUSYybOY_7jP>Vo zu0r}o0)ppT>p{KP85bZYPe65@*~^8TU$*|Jn4Y4!xpfVKpLsInR^GEOJdAztuD7R% zXMqFOT9YV6w^6G*99Y&x$rcp5qSJ0(bO7y|OZ6bdWvmZh>zV`Tr4rM^+ZBW^ zMY0fnB%nf(YdZ-}i|NMSXiub9*sXr31xm*(N-LU#L`Es2AF8L!+*U2NJw>DpQ>+>8 zsj?vDB-GSsEis%SY(iS!o9hj-i;%e0>|;-hG`#Q=yC?YOkC=@dALU$Az&gl$OaCN` z%K5$W>r`+V^;M6qVXBdyrO&<^qy31&R2O1Y%th-oASE>#`Mo9s9M0LUDc>Y@Nc`sg zbLXfxdQH*KBAtr?5s`0+_ISZsMdvC6)b@%Ne-iqWfAo;Vi;QBW5u^s_U73Gylt6d$ z#WO0=-~%aX>1HZ3zm!J`8J>?qW95VgSU+Cf!JmExFebTkFeV%Ju|6>taz}Wyn%75Q zwn2)LlTVo~42sR`&It-8?odzkaiT2<7qp&S0a%pk+(!?QzeFP^Og>uYKZ+Dta`DPf zUtm))O40HrA;C)Mqqr#rHcskCGL{{IQ`Dd4Rd^DBTKQW!ZWY5h|^QbFbGJ!S(p_7g?!N2xa)XnBp!&bbE8xRh$CKjhZ1$Ay;6~ zbp+sro0rE#J^|xx0~rwfB1o(Hzfgewle6 zMg~L54{{maHXS|{4Q_aU0d%G_4gsZ=R9=x1UNZ6r0mjG|F!=!*#^1jj81w39gN{9c zR;io{X84mF7=AmXV7x1tp0zUbXJcDL*kMWpB5aMcBQWELsrufK16st|Yb zK1aX!9j;UtU^>2)k@#PT)*6EjLv_H<=Zs7GG>AV9OS|SR(&gT*^HsiLZn%q=!3Dvb zv<~K)ceKyQm*-8er_rf+SVK;#>vZMy`;7^2hIP=;L-C2g2VhkIMv8tL@ES+M(+))| zb&yX?sz+pgr5Xx^+VyYcgs&!Cy64Xhy?s+^R(L50iO$jR`@(1-LUX4gAklAbX6B!g z&|t+rhjj^n07*!%y|Z|4cYMzw12b8Le&Ij(i?4_9EJ(=2I|6=gk8 z546_0ItJ-D7j`IONc=-O4}@e?fJ%9W1&Vi$@>>KGUXLZx5Zv94!}0O)Sm2_0 z4*+sIf#>J#uLMmF64K-Uq1iwLRG8Mj39nN6RGFa9on?Ly@1h5&{<#9C{Y%$p<;%4Z z8B_Np4Cn$JyL*Q$k=hL4b92UQfyI%N+D)Ty06I!*V$|I}7tAXyuJQI*gg(lQy|J1O zTOb^ED|bfs?V;b2=q;D_wWEWL2i8Xij!&@O`F}vJr(lGp#1-l!Z0Eh!ai>XISu_;< zAX?Gt2*2FMXWaiCTG1*DpE*iOYf5uO-34^U^9ZAtA78p8zYkjF9@G&Upm~oKeE4L! z$rv8}256|Gn;{-9w|@Y=QUS;&ut?4)Y5;+Lr~QNQK==%Vp9o^qc_im!4f3RFi~!`Q zrS|`T942hs@Ir<^zpenBliqVQ&nn%(?dO1utu_gZx{1eJcRpM`f>MFvz%^*3rPgx; z88}urkLS&gL6hHefK9g{kG!#F`MYUQ$fR$@Hf#`7oj`_TJre}2B|eZ2G;WE*FeL)S zcAuKt@Ea}TxvbU=n4x`YyNp&vP^=mglYDKEK0ru(OC44^tW5^(8P4J8h-qiRaCgW# zJiH&QK?m=cWx|K?{I7nwO7scJe3JmWp6{isa`EgmF@Y1L*X%%6UL+Bik~KIsH}K_4 zPsoAPN&Kpxx&a6x0ZqHZ)K_l>ULHPcsipaJ%H`@Ak8Xd~q8^)JFCnQ0JhwUj;<)UO7Z|YrNR{un3 ztmAJz3gx~G>{G9n?W{%tz|0qLiwN#e-h(ju9+kl8Q9*-#qxy&olr2(A-~ zV=kj90fGvT`iE}-XMnZdcjEPlHE9ZJY7?0O@WRL}vbQZDgi<*$&o}D2L^cZXh?F{% z5D_e_2H0{kh3he)5P4NG8&>1)!FA`<0dsKVYFFn{pNw~y#6vI&r1pR@vP=_qhE6bH zb;jh|uWCtAt}`(+H?Z~u?{g}p_?pmiSEmP1aQQ>7B13RW6ti+qFsAk@cAO>5!v}MV z)6qYeBzoIssxfoSoUrj=%L>dKs37-J6~AQT9qkmn_7`)VjL$Fdh|tu3Jx5Sz@eq0x z74vm&-={2vQCMln7Z~+tzZ2qzy1aKsO?DCmog@{q=quG@e&BV1q^24Ck7f)!mKOxs zT_l86u(^=TXUA{HXaDwU6`|8i*tOg=I(*WJQUGX+wyl}dK-oP$fh`887A8fnPfGF* zSGf*Z6M$<uY)1QJX zcSfH^boPYJkFNb7-7)UouR3nfhkGxopL=;`cN&}0+k*08`>f+MSRIbhYG{}V_j4FVYUUOCkFq6a)+S|Fpe^u1l6L=BJA?v|;(%E?J9 zi&v6fAUmJ(p>!AkH4;B4?tV&KGx+<|-mWPeJL3KI0M1<6Zj>Pc{+#EDw`|sk*l_32 zi@P7WJg4p254ehJGsH7YTRAT%`9RpIGnr(j6aWKu7W&!*i%%EAPKJA5Ve6zxhUfKK z-+&-v1_6t>%LueS8!djt{EiXs#y6g7+WDjfvIL=*nf^WU4zinHDJ{E3`6@dZdte}PuCX_A*r;WH1 zU+J;XVxrhEQ7u6hBC)ES@6($h6`ZyFluiwG^2Mj`^hexLLq~S8?lp} z?@c!N^|dZS0re36Wl}2Y-IuIbbHe89)MqC^`|An_w%RmV?1e)1h)03dQ|K7(OR}bv z*Lme!OKv9Uql@km4%RmdFvLdT3V>gkP=DZ-P4v-2^(RumEU6TB-p>9Sg6s-;kVf9+ z44t`jD0PuMXd`c8MCuFI-VS_jXJCO91?*wpOhQ=&)EMAoXq6w(f(RWDsC$b+z(g@2NIk0DKVYVr0+iJR^_Cs{egYFE9D9 zw95GZo2|GzjC~Y`AzOaEKBk90LYKc=xAw+Hg_&U)j0LEFv7mDb-@5u1GTvY4cAO^a zutd=(y?^SL^AkKp?KidVG}9Lv&3kzt{V2cXnyNh&R%&F># zKe_EFWm(}u)VBFO^!zzsapOVvu%^mjMet-5a;rVDB5)Kecnaj(1)cq@rM(CDgD~wL90I9d%{9nqSAbL;SdG_R$dtpbq zx87X*cnSLq)@e!}!-ws}WMtfldJVR0GiR<{k`AS{i+Or0jQPqfES^`g;W~AmzW#a= zqTe^Z*^VAAYF9rtS=u$RHz+r?v$vbs5&OPhqcZnyIsUMuI(K1VpRFEQ>-8O)v&6w4 zU69bA=sP}Kb>FFmE%J-~xlaRpJ_~Q%y!vSK%KWe30ihZ3tcY#p=QkNWLmw9P@ke-h zo>wB*VzHJ(%Xm{Jf5^$X%$}4~9XnITPSDt*j{|j_QQ97CjHKme)RmB!d=Gp~bw# zj|F8^-L=BZo}{F%?of23<)*Bn5?NqQ63*m+T2$xQ{(N*;x5|lVE!+&|3Wdp-B2pr| z48`z#`%p5)+eyKmbbjU8OrF0RojuQ1UTH$H6i*CE_MzMk-O2raWeN$Yuv(RoNioX4wezdYq^Z(LvvytvJO6?cS|Gn zGk-?M$c%>&dO(ewjEwGT8`zJOGa(6$5id%j$l#9X|9sYY+QdV(^73q7e+ByOuCdxx z+sUc~Acvp>%Jgu5o7{a2CO=7DK0nFm8A*{BA$VmuC2r~Cp{(;~c;sk>uMxMrBmjON z>2F^_|LF6e{u6`{@J(!le|}9nPM<4KEDEQyTK&2mk%K+<3Nkye7;{UuRC2Sm{>Yf!Q;5kjr zVG_J@1p+=B>MSr!=B0fHTY}*T92f|Xm&@ZIK64&2g*y7Ts^rxAXQfhax0y^ebe~`jS z)!{J-%h9?%o=tm`BD)fWQPUP731152S}l(F zVX>0P9-_t8L2SxALX5Q0O^Q*uNDk`=qM`Er|G&L)-Kqj7@LCz<2oF19U3QWiR-S`qd zNK=HvhXx+w@Ardy+;Yq>w=yMHO9`7)!`o18LK4zVzx)TJ`@@Pbe84AZT;3`nf!lHc zL%WUOezaw=6mXD^BKz_abSxs}R38KddK3baBwIdnAFa9{JO6}jP*9Usenj{nQXC&H znliTe6y|Tp2t;gG=-Dj$pxF`i>gUn{`Z2~X3C>zNH}-Bsb<2}t8Y8`zCZlY5jla`a zZ8_xHm1h3}UfNk$?Ig*Sl$YLpCoDP|WU z>=1qlt*B?8H|UPvD9Tg({7aKYgE(q(a`MWabD^5^YdCR=BoCDFLd`x#mjoln@UO%C zyr(Ezaoy+(DSY7Bvu8~fSKIHy3tk})Nd0+WoOxMALmG6h*Q4%^6j8$;a{DFQ*cuZa z3jIsxerMtB$B{RNJy7--XaH1zc+#TL>Uv4gl_VdvkaiNruX*O6Ujq@nLO{_ zGM7WA%g3fcuV7l$@sTs1UIVV`!-pS{Av?eT+)0t6GN*T5;@N`zOGr0x2IBrh>?3 z;wAC{Blft%7^TV9Lf`9A*-BXFya1?fYDlSA>1N66btqhCK;QcNV;J^i%s5xG{qPG! zvCh-q5i*^ZX!XH-2g`hxYq2EuY9AX1hgo_x`xqG5z!91U(qc*cSC+w9RfR>|nP`jh zVDy(h zRALM)=iZ+1x+DjA zxdtfWy5v(b!jhdl3v@r@omY79wxHl^sl{ZBS_G1_WjuvOeHG|D?b!T%F-EI;xnw94 zQf9)6+t7WLd57@kT|T4ETR{xsqs;r#D<07F+*U!9*7}71$n_x{nU*+}3Ch2<(| zy%7<3dFX;dx4DNxF;)8iO{z~k?`)-!sU-KDc-@9EzD+8%g~i=bqs zZ>U@}Mw0JqW6a!{K?dr!go7!EP>z)~`7#~-Boj20P)2)qvJ_FzEadiN*u+;#r{s21 z-)g;Av6$~n^e98o_iTwD{nn3YAfn{1QR4+sS1~NZfWN?LY=`H)l{je!*v%mnojwh6#o!EkM60pWha|+eGVa zR8cy$@#=6{p-ibebVuK%TG2+?*$tTsDEsV$jf*)HIl`n{AH+)xEU+V zqK6ozqjCwO!c2%H2Y6b8yS4+*2Q+T?js=|a^78U&1{=e`7Fxu#R>J=E3AZSnOtEYB z6AhXDvf2123!=-&5INduF{ck$<=xf#UV9EJpMCW4?sxahr*=OYhj)%f?8mU2*tS4U zhKkBpzAm;etg|GzyvTnq1KE{yjP{N4MP$D6vB&;^HG}Yq;dflsyu!HeQPwI}cJaU8^4PGI;!nsa%JPu7tjR}Z1f-HLFF zE6aW4+2=!|CJXdjBq2%LbY;!q0P90OQ8YLa?H^CcILGpvw|^2m3YpDLre+$3oq*DD z8c|V2ryDGpcefS?1n`@5BWab<`JFZt zjY$%7`E8ZzzS;{zmT~jz5YY4Pyg!~5KbB$pqT_S`jVN-*NN*^tV!Wj2V=f;rq5=Ik ztUT{6cL%DEo|o)Hq|Oq>q?iXVdS7SWn})ZNfuWKPPW+#TINejO)wdl*Ce|>uwz5~A z?*!?OC%_TXGY>Brf9Hpqfu1D#QMNi`7V=ak4Qqm1^8b83S$bb3sD|mji(jLj&*EzB z7vx$I7x8*PYj+A=R$mAuPaVfYAF1l7Q^?z2CcU;RE~(1SpDW#FGGLmRr-nN(5!zoW zRE0*zKB$Gp;<`YC!wF*E2yP7dnSXNmo&`j07uXDTmk+v&e*T6c= zz-8hvxO8Sed9jd@o(U~^EF*TQ@J&jWF=ClTCSWwyZ*c|V9`#DN<5cy!ODiBzO?&d^ z8^+=QhTDPb3_~Ejppu^P=^zYcks_kqZM`hTjE0yq&jd1>ey`7mR320x?^id}#pBS~ zhRV#q{Du1lwM;%1-V2zZRf)JF-wVlQ%f0bQmiU#|PvSY$?avH_X*x`J8B9FDx3I5s zzWAeQ43BwsP^@*Oa!0F>ycLYHZY#|VBb|O8yl;VfP}El0nCa-4OrDLi3Eq`cPd>Al zUa|2_xP%I5oq6I9pG}-u9zaKf-$KfwFs#CGOokpp+%W3BXGS>7U93x)uI&EQm)q)o zgAvF(1YiTV=;>d8mg)My(!B#LwE7w*v?_gh_W<1+pTM8_0ORa45N(2VLV zXBJ;Wlp>5Llpo-MtofTMmj4X)Kf+N{R63-}ixKUNmMh)OMC(vmk*apz#Vg zn$otLEuEZxyr~D1m&>@ovprj*_jSieAc~BHOd1XCMQ`p9iS`D@ye;uHL>vN`mod}Q zXH?u|xM38!2X=>axoUTY1~GdqT0ZjVWm^Y)1A|0biZdM2H9Xy;fR?;LO<~tH11e9Z zs6Z!CsdvIU(I3>A>KlyjvRGSZRm!rc1WuUP$`{kO`bAHH=aVp^A+7pm<2}uDUE@zd zGQ#w4S!*}f%}ahX$pyTH^7h5zG=7PUsiZToz z4@+=(@XC3kYp0nh#8zwrk0nlLL9c-F{dHrOl(WAOn`+1xYcy-@(|VS{wnj{qVP^~U zcn1<-5Mf-`Oe_=q?qK4rir)*OlYq2Pp(fW*E0mC8#On3wH_*{ULA*^;6 z>`Kc{p&Mf5G)BF#y&YOKMQWtzJJI|s_LHtwpm*s z#C!-aO-R`5t9NH&4gA5?0%uRB715^QOCX;QT)}DcvlCveC@dQoxh84&=mYZ0K9CLz z@*rVA=9cgNkdZ<+uCYEBvQwY*vNYzE^GJb%7E}nA^&BCb$vB0vVH#3d)R#l-gcTy4 z6GJxcpdF=0kxYQiClOh+by9#Ko~0)+ZOY?BCFW%vDA^b=)5_<715;M`c|YgNs0qn| zPB|FydpUqo+%*H*mlw}H|D2j9N_O>~9NIc;95x$YXIiP@ho?{e03HX*b5qR+wsgoxwBzFxHTn!RppRmQq`q?>rvq-Di zpK!guuX+1dppM+R#>lpAM2EJV;^q{~&EaJ4PMqowQJ;P)w!+yA+DBJ%#5!RQ06RVy z|B8m%_a|rzjoEJnlcZ>%DRoI)zli`qV%RqJKyO`N8+>EhR06@sXR8Sb-p@SH))+B3 zdAz-LOS+E1VfJ2_RJRS zSB>hWV6ngY_WR;J_x*R{(N8Qg=$+;gQ~1@T@sfpV!`{=`4|l~Gor)VrzgW!Itsl(- z#TrGlqPuz(zwLD0Q>9;R3>b+R_hh{;hc5I!LSvzYfEA%;H>SlfwuSCNVoyDYGb*9Q zWC1otsz9N!d||A*`lj;2kHYkf@=1U8cHcIr8mqvNmORypaM9p1+8!3`)hW>K<}2>Q zW`!Mcj*%&@&7q8G1j?)wTw2+q4pZm)z|B?e|6)0Iw;aYw-|f`Gj$84g!N7ikjEg*vY*_@Pnvw-uCc+7v0gc(Pob4BluP25N~;2^TsV<=6!O75OBO1`HJ`3 z>bU>Md9($c}#{p)H<1k9ZFiCAd`d+7Li5|FcJHX3b1l*< zAYae+jAdE>GdF>dMNpSQ`<;W+!I%br8Q9#E86T0u4>GGEmfM!iTiscCW~W0dz`##rn&*M#VO<6~8g+ z>@SBAz&pPyETZ-;SK2bdF8g=Y;r3AMQLSOsltvB2#k}}GbyI(X{_k^<e`@24=0j?wN4N1MX@5lQ5TY^OPH4JaXL;u1{KDbMy>w_EOr!k^S&v{-@j6-Sn?+V)#m8TrZnv2LA2D>Z`3s^eiCqFi#~@HNNE9i$GX}rp>LT3f zPF{jsgMc|w|3vWB0CvDs@)xJ{_F7rNx~mAic2p5mhaifVK80~2Q$L4n3ooDiT!-UI zfMcv3hr~+=ZOi5~x5?!MP|fz-wddZXR6+QE1ER>q_~C@^vs)x?kfUi9>t z7ZF5s60QW|*REZ&xP)+G$hYT~GOcF3fpl0zSC%zSAxRUqaF62IW=L6PT*EjY>|S5d zUT87+(hvCz*&$=z>Kr8)wRH}0|B$=}@n64NL$jDfa>R!dZ(5tC9ZImQ7$S1khY7Ew zuNY_MFhOA@*a?64iz*rR>I#@VJI&LQ=MX>NETN#6>mFiNw4WDb{`W? z;GQjd+lCy;;?JuhBZ{?+q52~>r@x(V_Z9LdDxyM;=Go?|#CnQ?8str2`<#~A-|^x! zuM?Ez3{!ZX4`;m2uN-z>BJ(Wf{=5pxx1TH%BllMUC!rOxHF5>6YjLcYEDomgfSh*D z-zj;HDi&+4LzxV-jHk(!cM*Nr=ZDUN4w;CqFlPzr;#zhnYq{cHJ7|H#e~ZMGzN?NZ zuqo{48BE5PSHXNa0A2gJ&PSc2|1m?BW$`lNkXS;JSSXlafafPRk}KE1jSuv&VT0%K zFe!P%I7ReqQ8A=I0qFUMIzu{9(IbSIS`%b>FA1npD;1C`5-1w~#vSHwS>iHDKHIM5 z`jB@6?ftkweTgd049P{0BEP4l%Bqxv-%Cfo!kWz;=#N0EMM!dYoMa>k+LOlZiYIB+EQt; z+xq6Di1R}~Rm>Zyq<%ZeNA_Vh}9HsG>--2X%5$)aG z6LjUMLgbJYrCxkd>Q$n^0kOIZ7_n&jzUY%VmUWKBe z-=kPOMn#0@u{j6)_HX~AV-g=sf<`I)Am+G_h38zOt$1yS#C@|$RB~S)YSZipbr^B! zRz2nfH?hg#xK1O(Zmo_>uYyHX}+i%(iIL!)r!D|PCUsjTZVKwlxQrLsas-ocYwXPy{6GG1&w zEAisw7Rp~w_72sS^F~kjCB6bdi}3BWd)6C|OA_6V_P6x-^p!L#d0FgtIIG;RhZ0-H z9m=t89$H+aH&>sFR$gGQioG5hR*@deagq6v)tif{^P9V)94wU>Q~@424lp-slnm4Swx z2iVsqg9;N^y{g87GK7qeU&{#RocQbSY(aYiBV(C2=^0je!@R6-R;@;Tg2#U0e5b71 zYFiCA^tVqXdQyTMor*W4!)@a%v`5<83EWz8MN{>Z3z*Ck%FHgGB z8nX~vZ}X;h?v(R5P6}=@Mc6$)Ia$tnnyQ6{zo#n2{31JUiz-lnHHRL3@6f-9()zoP zC*38BmRph)e?7Q1cP3kR@;{VM$^pv1wFb)H*ynU~85QKScRFHTRBPa*YW5ZQ=9YG0 z&rRTpd~-GBJ$5Mmhu8!;Ds9|0lQPi^!ZJ{i4|B zvl8ogm{UIwO^xjStGZrL%iCy zjWz18r=)|eee5hXq@}AS&(x|URT6xTRHE+7=V@+YBu4p)e{)k{*=wGXv3W2yRpC<0 zt3Z{SO7$0sZZ@@`uY3*-b@~4xl*qTD&jd6+onkiwi6x|0{`-6CxyGDs^L?t$IDE?6 zKUNga`qrGaBT{#&vuX883nyXU=tWTA#HUjJU*|-{=2kphuH4U^5fm^Pyfxx5jio>% z%WFI+=(*jZ8~F1?M-d%J8neW!$p05{eHFKwf~en5wJX{^rux^!y(~Fk+LxJnZNcTe zvXpV!Irw0$1|B6*<7`gE0D6X2Tm9F|f#+%Xh69tAij)vyVV=#%5Jfs*!vFiV&eCwn zy==XjgNraeg>@j}?EE+0!!QSs<5Fe*Zw!i&7~tptLFl2l89;hQ*>C%Lvy!Z_ z%Ks8xj7-u>I1{6!w{3j3*}%%lg#6nFdhQNM1AV%u{u}FJz6e9m@Jh2Q__&M{|Mem; z(t5{;Ym%}>;TOU78c>IX@L!U1DYc5@qNiv5e^VS7fhJ6>^wno}{**DI4Chb!x91lv z>JnoG{_py)4Dp{Y0Eds`UtX+gTN>YQ0y_ydf`9p~nW>4}V&>)=w{h1{|L%LiNEQA! zRs4rPFf6Ph1}6EbM~E#`O5MNw)(mRGFf1q`{YzRZIht_-FOdCP=A7=lwO?Y#3!j@I z_%B(XjVSm01L@2E_CVIXJz9A=tn5fa=U)myqv9jy2SMRKq5g^WFDd(sUcrNf`ToBZ z0gfS)M@C4j7TWqRZ<%@HMiksbX6?UYiiU(M=x>My+WPAQ%wBHyOn=WP&J#~Q+FiSp z9<20u?SGli|EMrx_xGl&QC{%Ezt5KyE1v5nKVm!Wm1!KoX;$+Hve!z>gg+jLikoNm zRDE`_SiicVK~FdGJtIPlPuF*EdE>c4Sze{(yslV%m=E1}uh&-A7j2b15!IzgW$GJ< z$8hz0y|jVVU$*-{FAtkDV*@7o;q}*jsj(dY*7FjY9CuZPq*C9Hbh>m&5v%g|+!Y~T z55KOM#HPv1t&4H;*UUeniWV^DDqW`TS?0h?GXG+sxBWeHmp6`o znhbBBJc#DqceceBBlpNXtE>gw`5?4_aZENJ;WAOx{pFeb55=GK zx^LoUw}N!^-~8X#a%6wpaX`Q&D)ueIV`tRXi^{yob)|M)d!RDc-~n|aeZ?#`-(GEb z??NN*hpM(&1+^@4k=&y~H?MaF;^U(P_WukkG%4YeP)MHJ;Z zxcLiBr6kLjmnow@*=s4#pF{13EZO_)-ZT`wKI~#q7W7#pucswbYvk+9(GjT-Z5qF2 zFZXoi(Q5T}BpaF;-cA>o^!R$Q2w z|6*jRHlleB@V4mO{dosg_dmEa8nII_|6xM}{9wdvgbhCUy7gJC4VkW{vyY`(4w<#trGM z&}u9g+j@#8@EP|1<_K2tx5mPdgp=O>+x_a38O9GzNSwlx%7B#&jTv0>a-?I$eS~QY zk`rO=den#J16u!Id+#08^aZOJM+#vbNKs$`SrEdcYW3(X2`jz z!BZz2F?Np`MZ7`?Y10oF^x?>*tZZ0&)zvK~=J3$esjBC39vCx`=YgEpAn2+P?h!C= z%Q3>5vJ-LhL|nL(r-)S~gV;lqOI^hQ2@Dd`bEy{?9*6G{sAzID)`m44H>0Cr8lrw6G95BWG=9X-AQ={%r4j0$Q{6J+c0(ty4 zvgNjwh2B(04prMr;e)At+VSCfvRQmdV-K9r%NK?T9lkNEvWI3x69HRX_93#Ep$^Ml zQ88`_BaGyX7nWGpCx!Acvv$!zLuW3omX|E&8xtS`FwQ>Kw4sdxH`*k-ZQGDcSQL4b zaB*Sv^DB;W9$F>#!+7P2-LuR?N%OV052rX~i*IZK86G%?3Uc|LVW?AA<**8qA-&B& z%{J(sQ25V4<6o>>90EF#cH)Hk{&_c0GPKm&R7(R^Pu!>A54hu@a9F zygON{ARJ59M4V*Tc|~@R&R8sfq62Mh$Q!a3R?{+}s@Smn(vNLpW@S+8skZoq{TK>z z<30(k<8tfwT&?9WKbE*`)d_RE!FgYk;hwlDSnDE3t|Gl+zFUA#nNxCB!ykeD-g`&| z%6g(V#v=C3yiJT#v{{Bzak?G{O>2t5{yUXMe(7c1-P-b%?K=(+19U0~MTJ9k#nR@T z#O?n35S7tE4b&{mMXg++6pn#NEz$x1(J%bMj)!sp!M(<3uEK5gWxuh85UQ5czdEu~ zl}9zL25zgPfry9gkZ&G~rkugQXQP%2I9gP3vRP|mK(*K&ZLX;)9tP|`d%vph6*w_V z#I5c|nYha;d1oPujb$_|)=?&D5=)b97vw6@9uqxTn-O}yrO7H!xKUdm?r|pf1xFK# z&4yVTU=HKi_y{4RNQdeD+K&#pK^ zbg`7zh&Xa>wWmr=krlpC=ep0hGx3_+AfMwvqw5ISE(0FbRq3T^B=Ftc$6biw z`rvYZli~7U_odU^ihWxCZVB+P%ETqOP(*1LhKv`WD)NpK8Te86d3-`}&{t<-phnlD zF{-;jw(_B67OIFMns_zq|0_hrtz9&iWO?|K$cyC-6Q!eKXVN z*V9^a>#C8jsifkV)+;Tydhl(UfCq-`7`lc86vjkKGD4Rv>; z_+>g{r5#v1+w9}d{F(#P{`*O*q2{;Cu4X0yKAMq)|bqhLDI1%BljjraQgFwo)i5^DyK>geO*!dmo68V?9@$;MCF^R6+AXI z81Vl}^i5H~Kb7-py|J8vW93b<0w7v`C)STw@#S(v`)+k!rGaoVri|~bjU=NFl!|?V zg~#9CGY@-Oh~mNXe5$GwH#b1YGafq)+E3CmnelD&>Ap`cW6t<6+3_3haa}ZJ5Ben| z{S}FZsxbq_G`Z=2I!{-lgdSWCSIX{?3LWm*7M_c?^NQqJ_KFOidukYQ+0;WNLH>im zbS5*xJp4;!D#d9wmg=dKSzAWeOjL*qa?f>D;sk+)+5A)Bz)jClbgI<;q9K2xQ`LCQ z$0s>dDzb{xnv#`igSb5BOYcop#1hqxdh^iosWDE{S=WZsPN@aHaEMroi2_K!UNJ}?zeb}RYh$fN zo_CaBAC>!R0SvL>G*N$ZqY$}%s{736*SJ!uSlohy?$t)+^M60u(F~%_1JgVwyUzOO zuFoB;EAzOyh^9w7(?&kHA4x`&-)1?yhjr-@Ufib*|6<-O3Ht5QcB-4>^1>fGz`{&{ zZJO4Pz+vqx0xeOGrnS=ffD`Xx8HP<*^SUuB8>RcA2@ z5t<1kQ3l?2%k?e)6Th^0d-t8Dt6Ss8J`JI$;?@toUXf2(VOwKj?1cSPmj;n3qf@q? zU;Q~slt4q{x!d|=-<oyc_>P<5^ABf?D|S%%=YlI9A^B(SaGs zyI9VmvpDHU9J_WH1B;~gnOufz?e{%ynyFt-U~O_#?2LX&nlEe5T9-2|Qa0#zo>JmZ zUO7O*R|^^qKurr}E0}qUGt*SS!-WyD(}X_|dmbGz`|}2gR2>mk^?G<8ON@BMgcMM% zEePh48vBpLeoBTS8s#ZK6@)VOuKh zx+sN%_2stf{&BQa4VuG+I!dCG1%a!s`+;F%0F=%>YIE0)zbBXCOU@EZHQmD*5$Qkk zAUiP{dPG816th>b;wFQ#WMYolLOg}SWE9Z|W9jDcN^B+4Sr~QS0=}}Z|BX*<699JT zJ|czDo?s3LXEPzHDh2P7*Ux`r=BA;hz`xI$J}v4I?MD{!QYD1K;CVMVU8y)m87%1wI|> zrpTdZlbi51v@F$>)b6Z#*m5d)`|iND2~>Bg*0DEZwYSMQj|e^Rwmxh)R(FW+hF0E$ z;rgSkU)H+LnCdhM+DG<1N1O}qGUo_n?&s6!W&*G)S;!OG>m4E!=Ar0dR!qpd-I1PVV-=~95 zMz)$?XNn4JB`uzDb;S}qx-C3yP4`+J3ip^)UVQDljCdkqa^pKrxdm`l3md6v&;CA5 zfog?@tn~%G-Lhg_qbSzAi>3A$p8C6zt0t{+jyAs-Gd;{cnW%6Z6{lyEYBd1XIgxb% zRqCLVSo-`*jPK7i{5PWcc3Of>qGd#QesK?vxBJ&)PouT+vbh$F<#u3J&nJS5TCIL~ zc$wF&3(nCkBEHhRx5sE{f&P)S;i+?TWyaiJUOzGV9ukh$`GV7AJ? zbEP=G*-{s#O9E-gI3rpr3#OzH)}7JcEqSlUnG0%9et1QiZ`f*t5)!kb+`BhQQFk!? zx#d2LVwatc_!igF#%ZO3BgCEl^<&?PZaV%y7+LjXvr>< ziR8f1mv5y1QOR6-mCZ6b%|67Pj?+WO&7!MR=w_q8aY0?3*cnANY4x5 zS)G-pO}ig*>-Oq}dmK{AGol>TJdmFNNjc~q4^l!2^cYYwuG{e?%uA}T!~K+e~c1wiqW5C9z=;3>WxbOrt3_BuS1c# z0HP|BdI@F`v;jGs70l0RmD%(H3diJrq&cp%=7B0Ix+)^AfSSrvKPS~=(_{cLof5!u zh&pIR>nM421r!-tz_D@XGSZ|N{(epKtMqR-V!@!~bLa)j(SlKk`i9H*ca{h z);khec@8zp;uVK>$0{sggO^k7X|l?&Yv^Q~ETF0Ol1i_yS&8Icd&c}$vWl-i9dNgg zO>Y($Y%W+fpE|{Pq#}P$*Ik=Z))J5o!9QakF@*6kk*UJC*?cuHsUb}&+0dV~;;^KT zPlcB0C}lAIEe(Z*HpeO~Rhz)vY_fZ6{WhKsW*xsLq>NUNHW0J0L$lFfhJj~{N5ZqcLz$yL3VD_^&l-EcYq2?){|GA zHPn1KTDUyqq(+d7^3R1#D%Xqfl=IJ)^7?AGYKq{8tmdh5U~X9cE#Wnc3a@)6f`rT# zTm-_eO5buZ%(QpS!jsi%e&#R`%P|xfVjhQ~h}cC!D7mxdUI}+g>pWa~D9*{trBQ1A zGfaK_#LkAWd>c`JkKCOILInQLS~?xcKH_}yPL3Dwi!!BuSsU4|%m$0~?eAFYCJWWt zg8aKD1N~d#@Ucs@pPW!>u?`>XxJG4(hYLa4SYg`BeK_;hAD! zP?LWSs%9^eeia88UA$OSfLo$Lg?&6Am;o^~rB7Dzp)QGVpv0fs+$U`|fk!|PT(PK^ zbXw_qJ9i+vdnp>I_kB3Mwb5!$PTSp{iI|m;;SLCELk^2i%{N{gkzj=b?ja>RNf&9BQ*$gpD}1F}6&e3piH~ ztp|vxgs$Ooy)StwSy)|hFeW#Pk1oUCu!$$Pr+$=GP!5Tf<4&Ss*bC95O|DHa(QM=t zVZHS4(^FmNS4ZwV(d`w=RP0dQ0@_~u5@wgeEuYQ3%5+*Lm&y^gm>P0EjuO?Wwi=KP zIJm9@MMj{8`HrP>GL%va;jB~baTP0`5eB=>shJr6gKa;^{+u!c+eT z#x=lqS9Ui+18k3S9;46NNbU&G;YRy+9z=|PpZrLb{}>h}LdbW}@`SW}FS0hBu_21N zo}Mf8Ocx_uo3l|$31X2F)q?iF={ zY_z^_cFAMjYh7mRWm`$S3J8uCWa|^eY?q};FBy68L@^JKv(HyDUv=N(_jk+L^;h7( zBnl}mN?aXUto_@``z!M_{#o6L{DdcI{PUQE+HLV}$lXuNxh4eCK3qGrTFp}#eVbIi z3EEO8E+YK#*_mKr%kbg)s=Dp}D*CR6_R~iREAj^N5|Ag{beEqhb z1*M!HsYWOkH?~V9i5j>076u-GuCVE)P@Ji@k8aNc`w}+FT-=(?a33s$59=Qw zpm~Mh2=eaLSfP%>-vpifW;<6_GpJ$!tWi?IVzOdiJDZ9JP+k_8*w%Mm1W%EodRZ5N zIZ8NxC#}yd1Sh&u|G|Obp7tMzGhc0*1Xo?u%NaS20vkPiej@&2&@fNvhxH&p(69>L zJr6>CCI5#B0z@o_r|}Gg8-oLE_!aG&f6md1xZlz1HPj!)qipOkV`z7=#F_lK=YwYWgq>F^*|En zqy%Y(T>2Cl4?}UnDhY@UtE^e_?1AO~$!7d3U-8#rjd!vNBnLTcQq((tlo8rW25N)P z{jvq*no-8KS(#ls>g<>+9k^jBEvG>e-5@Q#1ucC{Q}I56Yg+kEi3Gz&f)XJ^G4&(I zcRWSxx?Vg`eR@%fkLP##KKTJ67D=HlqgaZO*&N8>KJ*Nz4ynKg(g8yS2 zxSP;v^j#bJnGc^$&cel!zikGNpHV(sT>eV?5Bu<@fNGd{x3l$ABrfbT@XwmE&zS&p z+uL7$+`&xywPGQ*I=WfPcp#FhvbZb#m=|gP9co@S1MBVMhqd|9M0C&Z&X6ef2pyQG z;nkc>2<(gP1W?)aPj^g*fYLtf2e!^ijw?F*tkTPiajA^Lm$1X=Yd~5YHGweU^o~}=S|fE z0sgF@<)<4CbdhC@6;@ZEiZAvVg)JB+W-^EID5e4V3%7~6e%rCjS@9^Ly>?qam$ab- z?0&W5Rod%Y!e0r5=x6ikxKco8l+G~CYhUlI`8)_K9f1UOX;3Qsh{uemdYaj?b}~Lun!m@)@)Z)luU3A z2^{US6{oCszP>L9@awmKromIFZke~nL8P;~WlJe_hCq>ZU%Bl80I zULiBjU3sh%7VwY6tjqidm=D`sR!|DBTAa&8IGGV^Ff7^QGEDOq-ma@%>QV(1^B0UFo zW(E6r$4zK$S{6u=wz}9-5B-GxpFGpAGy|HhNnk)$mEeLw2A*KV^uL@u)6|-rF?Ivx z$xpvY6J?Y*9UFmSqHa)xbk|<9<(w<4NYEpe#3cXP>rD7YUnDF0%3s?e~yop>!%?bu~ZL(Nr(+94H(9 z#E7HCF{TeXUt23xtP#8m7gJ8OO1lw$cJ7wOmOetVDCOWt$PQWV-A(rgqaWDsayd$e zleo|K)u|OBXKG=6aYi@}Lh;AHKf2)(@nOCv?I*Z@WmEjz3&Ee1y1l;@T!vHIMHI}H zI5sbrSPs!zxt|sawF&Q13cJUn{3;i(FT;XLmkuZwE?s9+tS^~*WW_#mFPd&1`h4bV zz>~RX=lLZ{EghN&=<18PbPV7NiOV4x$XQ7ia&IB#Ge}5y_Z<;gd?Mh^j6Mc)V-(E{yl2e5HCksT29vpmHbH%#O zHVVPLZ*(}|XVpGbU=sBXfTjK|fK&F=9qR>b=WqWZgYci@Hvm3n^BQ4|A^$nx1n_3Pzf}4EHG2OmxdANdlm9L%z*+tqV)0+n9sga_|CD3;?@9gd z_5Ua8^DkuQ|9@|4KK8wk6Cng-&iIFn=h!j}p4tdPvkc?#B6>n&8kBT>rXw z2HV7~Ra*$ojXW=5t_lQsw8&9mpG)m&^gS-bZQ{9uZji=W-eZ*bqmcE6vWaqMX2`en z!l6+h-kk8SGK-t2>bbm{$u=Pc$(8?e&+Xd7!$0b!LgI8xhWQZg2>bdcFww0qMJkJO zybSqpIY<6SRbVH`zHD8hzG*g&!+wEzD%I(wAawIKM;=YZerUBj>aeJHgMzdHo( zsd`M(mk`VK+h)V(#rGuV4Znz$=my-{n)$o+S*;gu>KgT^wr{I=l+MrKs#g=C$w)V!X8x{JWdW2jsyIinwvUx zEbEHzN1c#ON()?!3SJ5_`b_4r#&?ez9TSt$9`CP?jA;5NN_G(Z_aINbv?#eTu3}XL zi%*dKfS2$!2djbUI%HCwR**&yTA*Ihs2Uri(~XYuM1;!fgr8JJW&(+j0b1mg^_h8! z;3|%{Xx~NpB{JqfhC%Zn2q#lxg4F6~U@?NJId^QB8k%&#c9o$o_huXQ61iae$9J4w z&m+soliA62F36?m2nBC#7Q+Q$TfV^*Mw{K=Q*23n?ZK-ZH%C(rX)UX6Yw(grV-mRt z+ZBTLOP?6k>jL z%R04qvRL!xc4(ywbuzs?(_esUUX5hxY65urE8rre-qJ()WT6zGas3FH;IPWd!4mV!RLo zm%tTBwAv&?FoGJ8e}8U;HkldO#*2K=?YFEGP#eg6FlX{gv9hwGe{p&D^B5da}sDR#TB08Tvr_2pwb8dMzhjrl$ zUF^UTl~eW}kYjIT3a&c9wJs|qzc58aTWJIRMO|3VHR^HL0t4wo-vKA9wdUh)6$U;g zKp=R%`Ajzd2B#98q+KPJChwS7I7}1CkmCb!NNGb?HUov2N5nZ(^~lM>VWV_m(?^nof*IC-qOsqX^6bYH8C+7N?X0mOpQ-u?aj9*k( zUFcdO7=Ac^d1{b-$A;PWon%OhB#kxST>Q;APpPF-*9@t}J)KJ`a;bV1MZuOsE_9>Q|=sIFOD=Y*gp+`9; zon(>oLB+xsrTydI?H_0bG;@U{;X=vx>q46Zt1s9RhXXjjy*k;xIQTU(wcWN>yjaFE zPIN=F{i19ZZZ3)nJmSbq{KLFXjq@!TER;LfwyNtgDhIBFu~A%bWZsBs8B$_rwGEQ< zt3Kob@>)nGkWv5T#!*QmYvx4xB$(M_i)BgGY0CpWeXJ{N;MK8$QNJHda0sHm#ARQxU)a4$*RA@+}c4gVHVd`SyS63xU@jQY3=SKt%!Eh_EaUnx@|$7uJ?nf z?IV=uf%Kf)=~Edz)yr3CudIKS0LL%b1lyLiLN&TKUuzV(xt(shwht@AY=I(k*P#qT z-~!i{&^CtR?V75I`u8=q&#C?6%wL`M@0|&*d#6cxoN~}j7Z?qBqvAVqa`*foEymWQ zc~e8NnJ;`xps-8^NOKZR0z_&cH5D}~aT6Jw-vwf}%9@zRvw1a>XSgZgjqPb_R{a%y zuMGlP(>7svEl)VcI(+8CaK$o<4G}y;G&pi9fzWk45PCtaGTG=xs<26-);83%)8B4r zzjTeg1qc1zFWVKR84?5)FW!bJ4ZPmvB*5e+73YZGdX|$%-F=RDX%UVwR-o{UsEu(9 zy9c_O`L@yk9357IH*$1lEn&kbuj@>?SC|u(hb>SXfaJ0}-{3}k*(6uWdm^(UsA-e7 z#X0stHtmF&T?^CkaqH?&&wXbx?b1f_pJ+=@y2&W7NZk7*;->wI`#toKKdWj^6g;U_ zr2%N7at2-v*!ak+oECJE$P4pn32D}cv+|Uj2lGA4Zq;Lf9T-01iI zsn1Lfs4i)Azj4-=)-fpDSb0@2(ir$-?_Q3&W1&as@0d8P#OwmLUiJ3csNVLcjV6Q1 z;)}`1t?00yH$!z z0FZUNxt9zjtZvisvoE-^hUPX;udZ*NYMbCtzP}Y!u^rfl-e}gN=r03?Z@rLAZOKS=ccv3 zAH6uZfZ_$aTVo#zDQlI}o$eohDLYHleiUhO-K^Pf``sN?FAp-zyBh?2CDmJKs{{pHlMQjQ>KiF z#Lm#o661Tcc&_u=OsZA`@M|T&=z)>=JH^#^p5vP_e5HK0d4Tn6b8Wu7>~0mgLDhsgv+H?I zxX6*-x?!ea8$|CIZur|nmL<mTB;-m1(~EL`^MH$?wT=oe;*cM5yjYFcO@w{_xZmaq$XW+Unsh`G<_b9)!ri5yPW;xFXHh0fIes~7swU?VGIN3h4|Y< z{TcgGW(ZOxy70kH1i={-8q(l$aS*X(kX~(>c@FjYA_5qgOo>Fak|cOXz(8(kqp3(5 z6&xkNYs%+!1``T2Oa+zRx65ktWEPfrVTA+9%;93fHT8{YIpv$hB%U;T;z+2vAYHYX zyO-w`AQ``3aK6WR`B~=ohh((hu94rBaOL5Zfh>JJ7g|jwKJzsYWbk z6qf3SM+#pQtl^sxMcs@^_{R0_Shu-UiRRPGWDas*g2WAb@d6}Ws5?omBS0@3)_XiE zCu4g0zE37k;P^STT9Mj0@TNVt^b&c>vFB`<+lTn_rOr* zY)jdc%Qej$E1PR1!=SoS9o%jbT6R!G0&_m0x3TXX4WakI6ogx9Bpj)K*qP`S{-lXf zUNIKMO5yI5HBWMV&8f~26N(=ZOLfMw9QkTSB`{ap*sXAOXlo(O;lRkIgt_T%g{#fh znv&KzL&P$Kv#08me{cW1r*@8`0eLC2}%r3X6)9I_&V*HE`_Z5scl%|rs~X! zOJ-y%``!&RSd|4Zy?w+)GpKTuGPp6hwme_%OP&&Ag5chgpvESMfC*}S%BrON zOD}4(IqvorF_c^BNlxP~>gQyby|a7G;f@=h$UX1!`Ud$J!}58hh6j`LgPhuDgEg#D zvZ?lB2KgwgUcXOY;SboKTfuky_KEk}=gPbLzJ^jB6Eej@MSBFG$=lT8l(nmYRFeUx z1FlOt;C#rjOevp}uV;7dmL!IndYLI=M(yf7^GV((rBU5rQSZx029@ahR&vOvPW(>M z!k;fzFP8VELUx6}&I&mbBE^?_PUrr!cnOxZ z!-~=em&C%XL-*}KHv%Ph(rNKTUDv9Oy6egWdB&-(rI(sk=!8^U74LzV+K^rA%>l_6 zI8W(&4~aAtG-rj5jp_|=OyMQLm7dI3!ONX)M7~k8B{ts?CJ&Cc+jz8sBqm|jHO-|1 zc9WtL)cmghFzL6A_>7(LT8{GXH*KtWPjMDbH_SGc!Mf}a_n*CvRK;MKCd8&%mp6K_ z5>FmC9j^EMeh=*HgSOBcx52;Vxe9%Rkk^vO^~Z5x_R_|D`hvu!&p9X#O7!;5KiP49 zsICRVXwa7I^h#6%OYZN`AwGDWQY>GkWJCOd14%YA8k#+|Yi~BoXtxuKES=(ECkJa_TSo1a1R7yE(`!(#<-;q>aqu|Pxf!%SF?v7f#(>JkxzS!FStFo?fTvA!1 zr{c3idDaoDe1L_GQ(HE~hcDPR6`j+R(#93{Vw0Y+C_FeCt!!#`D^riU1NUHLzmkS{ z0k_dk1T*$+t`DjhXWX@+jyKlk#jB@Qg)w_sx6i?VhoeeFLC%vrC2J`ta0Jp+Q>^Vr zITV`c%h7GKY}+k!V3i6DYKVP1m*kEPUrkvxUs2G}%z8If&+k4l7!qUf+xn_HJyTt6 z-wjVw`zjP-sr824Fyk`s~+3sVl57 z5=t|-agCv=3|yx>iKXMRi0uVw&!}FvF>ze_1{(2}+*~3R@yqNw;%j!eK1La?k2rsw zbG|%!5Pu2W!F15W4-fi~dg^Sw&F(1Wvy#zNpMKHYW(SdUO46)n6Ly`B{!XJqA^vkx ziA(%t(S5d*w$Fu43Qye&gDej2VMZ5gv{hNFq}S?hhKG9TURD(N7+1stbr65*CLXeu zs;#O=Q&+)Q8XBquOhHF=rPHDc`hdpMqq>*t<1?!g!~g!;|Gp&3jfZbFN!ZoMexU3= z>OP|0|2Rr-+vH#`c9i4?aW4dxGVk!qXcG>hNB#fO4{7s=R{O(n>8(??)Te+S6$P+- J(S5TQ{|BM4=Rp7f literal 0 HcmV?d00001 diff --git a/cmd/servers/atenet/main.go b/cmd/servers/atenet/main.go new file mode 100644 index 000000000..042cfa5df --- /dev/null +++ b/cmd/servers/atenet/main.go @@ -0,0 +1,21 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import "github.com/agent-substrate/substrate/cmd/servers/atenet/app" + +func main() { + app.Execute() +} diff --git a/cmd/servers/atenet/readme.md b/cmd/servers/atenet/readme.md new file mode 100644 index 000000000..500cea38b --- /dev/null +++ b/cmd/servers/atenet/readme.md @@ -0,0 +1,42 @@ +# atenet + +atenet is a combined daemon for all networking functionality. + +* DNS server for ATE Actor resolution: `atenet dns` +* Lightweight mTLS proxy sidecar for demonstrating using ATE identities. `atenet sidecar` +* Envoy control plane for programming ATE resolution. `atenet router` + +This is built as a single binary for convenience in the prototyping. + +## Cluster deployment + +![atenet diagram](atenet-diagram.png) + +### router + +(Note: this deployment model combines Envoy dataplane with the router. This will +likely be split in the future for better scalability.) + +* `atenet router` will be deployed as Deployment and Service +* Deployment will contain: + * Envoy + * atenet router +* Service will expose: + * Envoy port 80 and 443. + +RBAC permissions: +* read, list on ActorTemplate + +### dns + +* `atenet dns` will be deployed as: + * Deployment + * Service exposing tcp and udp 53 + +* read, list on kube-system services +* read, list on ate-system services + +## testing + +hack/run-test.sh will execute a local smoke test with a fake ATE API server. +This does not require any cluster and uses the fake ATE api server. diff --git a/cmd/servers/ateom-gvisor/ateom-gvisor.go b/cmd/servers/ateom-gvisor/ateom-gvisor.go new file mode 100644 index 000000000..7d79dd0a2 --- /dev/null +++ b/cmd/servers/ateom-gvisor/ateom-gvisor.go @@ -0,0 +1,585 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "flag" + "fmt" + "log/slog" + "net" + "os" + "runtime" + "sync" + "time" + + "cloud.google.com/go/compute/metadata" + "github.com/agent-substrate/substrate/internal/ateompath" + "github.com/agent-substrate/substrate/proto/ateompb" + "github.com/hashicorp/go-reap" + "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var ( + podNamespace = flag.String("pod-namespace", "", "The namespace of the current pod") + podName = flag.String("pod-name", "", "The name of the current pod") + + reapLock sync.RWMutex +) + +func main() { + flag.Parse() + ctx := context.Background() + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil))) + + if err := do(ctx); err != nil { + slog.ErrorContext(ctx, "Error while executing", slog.Any("err", err)) + os.Exit(1) + } +} + +func do(ctx context.Context) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + slog.InfoContext(ctx, "ateom booting") + + // Create ateom dir + ateomDir := ateompath.AteomPath(*podNamespace, *podName) + if err := os.MkdirAll(ateomDir, 0o700); err != nil { + return fmt.Errorf("in os.MkdirAll(%q): %w", ateomDir, err) + } + + // TODO: Consider whether we want to fork, so that we have an "init" process + // as PID 1 that does nothing but reap processes that get reparented to it. + // Then we won't have to mess about with locking the reaper while we do our + // own exec.Cmd calls. + go reap.ReapChildren(nil, nil, nil, &reapLock) + slog.InfoContext(ctx, "Child process reaper launched") + + // Clean up any old socket. + sockPath := ateompath.AteomSocketPath(*podNamespace, *podName) + if err := os.RemoveAll(sockPath); err != nil { + return fmt.Errorf("while removing %q: %w", sockPath, err) + } + + lis, err := net.Listen("unix", sockPath) + if err != nil { + return fmt.Errorf("while opening unix socket: %w", err) + } + + // On first start, scrape from eth0 interface. + // + // TODO(ateom): Save to boltdb database or file under ateom folder, so that + // if ateom process restarts, we still have it. + eth0Link, err := netlink.LinkByName("eth0") + if err != nil { + return fmt.Errorf("while getting netlink link for eth0: %w", err) + } + + eth0LinkInfo, err := scrapeLink(eth0Link) + if err != nil { + return fmt.Errorf("while scraping info from eth0: %w", err) + } + slog.InfoContext(ctx, "Eth0 link info", slog.Any("eth0", eth0LinkInfo)) + + // Create a new network namespace that we will pass to gVisor. gVisor will + // read the addresses and routes off of every link in the namespace, then + // remove all the addresses and handle injecting packets into the interfaces + // using AF_PACKET. + interiorNetNS, err := createNetNSWithoutSwitching(ctx, ateompath.AteomNetNSName(*podNamespace, *podName)) + if err != nil { + return fmt.Errorf("while creating ateom-interior netns: %w", err) + } + + actorLogger := NewActorLogger(os.Stdout, metadata.OnGCE()) + ateomService := NewService(interiorNetNS, eth0LinkInfo, actorLogger) + + svr := grpc.NewServer(grpc.UnaryInterceptor(unaryInterceptor)) + ateompb.RegisterAteomServer(svr, ateomService) + reflection.Register(svr) + + if err := svr.Serve(lis); err != nil { + slog.ErrorContext(ctx, "Failed to serve", slog.Any("err", err)) + os.Exit(1) + } + + return nil +} + +func unaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { + startTime := time.Now() + + resp, err := handler(ctx, req) + + slog.InfoContext(ctx, "Handle RPC", + slog.String("method", info.FullMethod), + slog.Any("req", req), + slog.Any("resp", resp), + slog.Any("err", err), + slog.String("elapsed-time", time.Since(startTime).String()), + ) + + return resp, err +} + +// AteomService is a service for shepherding single microvm. +type AteomService struct { + ateompb.UnimplementedAteomServer + + // Let's go ahead and assume that Ateom RPCs that are running `runsc` + // subcommands are probably not safe to call concurrently. + lock sync.Mutex + + interiorNetNS netns.NsHandle + eth0LinkInfo *SaveLinkInfo + actorLogger *ActorLogger +} + +var _ ateompb.AteomServer = (*AteomService)(nil) + +// NewService creates a new AteomService. +func NewService(interiorNetNS netns.NsHandle, eth0LinkInfo *SaveLinkInfo, actorLogger *ActorLogger) *AteomService { + svc := &AteomService{ + interiorNetNS: interiorNetNS, + eth0LinkInfo: eth0LinkInfo, + actorLogger: actorLogger, + } + return svc +} + +func (s *AteomService) RunWorkload(ctx context.Context, req *ateompb.RunWorkloadRequest) (*ateompb.RunWorkloadResponse, error) { + s.lock.Lock() + defer s.lock.Unlock() + + s.actorLogger.EmitLifecycleLog("Actor starting", req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + + // Contract with atelet: + // + // * Correct runsc version is downloaded and placed on disk. + // * All OCI bundles are set up, including for "pause" container. + + // Move pod eth0 into interior netns + eth0Link, err := netlink.LinkByName("eth0") + if err != nil { + return nil, fmt.Errorf("while getting netlink link for eth0: %w", err) + } + if err := netlink.LinkSetNsFd(eth0Link, int(s.interiorNetNS)); err != nil { + return nil, fmt.Errorf("while moving eth0 into interior network namespace: %w", err) + } + + slog.InfoContext(ctx, "Restoring eth0 routes/addresses in interior netns") + err = netNSDo(ctx, s.interiorNetNS, func(ctx context.Context) error { + loLink, err := netlink.LinkByName("lo") + if err != nil { + return fmt.Errorf("while acquiring lo in interior netns: %w", err) + } + if err := netlink.LinkSetUp(loLink); err != nil { + return fmt.Errorf("while bringing up lo in interior netns: %w", err) + } + + eth0Link, err := netlink.LinkByName("eth0") + if err != nil { + return fmt.Errorf("while acquiring eth0 in interior netns: %w", err) + } + if err := netlink.LinkSetUp(eth0Link); err != nil { + return fmt.Errorf("while bringing up eth0 in interior netns: %w", err) + } + if err := restoreLink(ctx, eth0Link, s.eth0LinkInfo); err != nil { + return fmt.Errorf("while restoring eth0 routes and addresses in interior netns: %w", err) + } + if err := dumpNetInfo(ctx, "Interior NetNS "); err != nil { + return fmt.Errorf("while dumping links of interior netns: %w", err) + } + return nil + }) + if err != nil { + return nil, fmt.Errorf("while restoring eth0 in interior netns: %w", err) + } + + rcmd := &runsc{ + path: req.GetRunscPath(), + actorTemplateNamespace: req.GetActorTemplateNamespace(), + actorTemplateName: req.GetActorTemplateName(), + actorID: req.GetActorId(), + } + + // Create and start pause container + if err := rcmd.cmdCreate(ctx, os.Stdout, "pause"); err != nil { + return nil, fmt.Errorf("while creating pause container: %w", err) + } + if err := rcmd.cmdStart(ctx, os.Stdout, "pause"); err != nil { + return nil, fmt.Errorf("while starting pause container: %w", err) + } + + pw, err := s.actorLogger.StartJSONLogPipe(req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + if err != nil { + return nil, fmt.Errorf("while starting json log pipe: %w", err) + } + defer pw.Close() + + // Create and start each application container + for _, ac := range req.GetSpec().GetContainers() { + if err := rcmd.cmdCreate(ctx, pw, ac.GetName()); err != nil { + return nil, fmt.Errorf("while creating %q application container: %w", ac.GetName(), err) + } + if err := rcmd.cmdStart(ctx, pw, ac.GetName()); err != nil { + return nil, fmt.Errorf("while starting %q application container: %w", ac.GetName(), err) + } + } + + s.actorLogger.EmitLifecycleLog("Actor started", req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + + return &ateompb.RunWorkloadResponse{}, nil +} + +func (s *AteomService) CheckpointWorkload(ctx context.Context, req *ateompb.CheckpointWorkloadRequest) (*ateompb.CheckpointWorkloadResponse, error) { + s.lock.Lock() + defer s.lock.Unlock() + + s.actorLogger.EmitLifecycleLog("Actor checkpointing", req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + + // Contract with atelet: + // + // * After we exit, atelet will upload checkpoint to GCS + // * After we exit, atelet will tear down OCI bundles and reset the actor directory. + + rcmd := &runsc{ + path: req.GetRunscPath(), + actorTemplateNamespace: req.GetActorTemplateNamespace(), + actorTemplateName: req.GetActorTemplateName(), + actorID: req.GetActorId(), + } + + checkpointPath := ateompath.CheckpointDir(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()) + if err := os.MkdirAll(checkpointPath, 0o700); err != nil { + return nil, fmt.Errorf("while creating checkpoint directory: %w", err) + } + + // Checkpoint pause container (root of the sandbox) + if err := rcmd.cmdCheckpoint(ctx, "pause", checkpointPath); err != nil { + return nil, fmt.Errorf("while checkpointing pause: %w", err) + } + + // Check state of all containers to mimic containerd. + // + // Without this, `runsc delete` occasionally throws an error. + if err := rcmd.cmdState(ctx, "pause"); err != nil { + return nil, fmt.Errorf("while checking state of pause container: %w", err) + } + for _, ctr := range req.GetSpec().GetContainers() { + if err := rcmd.cmdState(ctx, ctr.GetName()); err != nil { + return nil, fmt.Errorf("while deleting %q application container: %w", ctr.GetName(), err) + } + } + + // Delete all application containers + for _, ctr := range req.GetSpec().GetContainers() { + if err := rcmd.cmdDelete(ctx, ctr.GetName()); err != nil { + return nil, fmt.Errorf("while deleting %q application container: %w", ctr.GetName(), err) + } + } + + // Delete pause container + if err := rcmd.cmdDelete(ctx, "pause"); err != nil { + return nil, fmt.Errorf("while deleting pause container: %w", err) + } + + // Yoink eth0 back to the pod netns. + podNetNS, err := netns.Get() + if err != nil { + return nil, fmt.Errorf("while getting pod netns: %w", err) + } + err = netNSDo(ctx, s.interiorNetNS, func(ctx context.Context) error { + eth0Link, err := netlink.LinkByName("eth0") + if err != nil { + return fmt.Errorf("while acquiring eth0 in interior netns: %w", err) + } + if err := netlink.LinkSetNsFd(eth0Link, int(podNetNS)); err != nil { + return fmt.Errorf("while sending eth0 back to pod netns: %w", err) + } + return nil + }) + if err != nil { + return nil, fmt.Errorf("while restoring eth0 in interior netns: %w", err) + } + + s.actorLogger.EmitLifecycleLog("Actor checkpointed", req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + + return nil, nil +} + +func (s *AteomService) RestoreWorkload(ctx context.Context, req *ateompb.RestoreWorkloadRequest) (*ateompb.RestoreWorkloadResponse, error) { + s.lock.Lock() + defer s.lock.Unlock() + + s.actorLogger.EmitLifecycleLog("Actor restoring", req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + + // Contract with atelet: + // + // * Correct runsc version is downloaded and placed on disk. + // * All OCI bundles are set up, including for "pause" container. + // * Checkpoint downloaded and placed on disk + + // Move pod eth0 into interior netns + eth0Link, err := netlink.LinkByName("eth0") + if err != nil { + return nil, fmt.Errorf("while getting netlink link for eth0: %w", err) + } + if err := netlink.LinkSetNsFd(eth0Link, int(s.interiorNetNS)); err != nil { + return nil, fmt.Errorf("while moving eth0 into interior network namespace: %w", err) + } + + // Restore route and IP information from save onto eth0. + slog.InfoContext(ctx, "Restoring eth0 routes/addresses in interior netns") + err = netNSDo(ctx, s.interiorNetNS, func(ctx context.Context) error { + loLink, err := netlink.LinkByName("lo") + if err != nil { + return fmt.Errorf("while acquiring lo in interior netns: %w", err) + } + if err := netlink.LinkSetUp(loLink); err != nil { + return fmt.Errorf("while bringing up lo in interior netns: %w", err) + } + + eth0Link, err := netlink.LinkByName("eth0") + if err != nil { + return fmt.Errorf("while acquiring eth0 in interior netns: %w", err) + } + if err := netlink.LinkSetUp(eth0Link); err != nil { + return fmt.Errorf("while bringing up eth0 in interior netns: %w", err) + } + if err := restoreLink(ctx, eth0Link, s.eth0LinkInfo); err != nil { + return fmt.Errorf("while restoring eth0 routes and addresses in interior netns: %w", err) + } + + if err := dumpNetInfo(ctx, "Interior NetNS "); err != nil { + return fmt.Errorf("while dumping links of interior netns: %w", err) + } + + return nil + }) + if err != nil { + return nil, fmt.Errorf("while restoring eth0 in interior netns: %w", err) + } + + rcmd := &runsc{ + path: req.GetRunscPath(), + actorTemplateNamespace: req.GetActorTemplateNamespace(), + actorTemplateName: req.GetActorTemplateName(), + actorID: req.GetActorId(), + } + + checkpointDir := ateompath.CheckpointDir(req.GetActorTemplateNamespace(), req.GetActorTemplateName(), req.GetActorId()) + + // Create and restore pause container + if err := rcmd.cmdCreate(ctx, os.Stdout, "pause"); err != nil { + return nil, fmt.Errorf("while creating pause container: %w", err) + } + if err := rcmd.cmdRestore(ctx, os.Stdout, "pause", checkpointDir); err != nil { + return nil, fmt.Errorf("while starting pause container: %w", err) + } + + pw, err := s.actorLogger.StartJSONLogPipe(req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + if err != nil { + return nil, fmt.Errorf("while starting json log pipe: %w", err) + } + defer pw.Close() + + // Create and restore each application container + for _, ac := range req.GetSpec().GetContainers() { + if err := rcmd.cmdCreate(ctx, pw, ac.GetName()); err != nil { + return nil, fmt.Errorf("while creating %q application container: %w", ac.GetName(), err) + } + if err := rcmd.cmdRestore(ctx, pw, ac.GetName(), checkpointDir); err != nil { + return nil, fmt.Errorf("while starting %q application container: %w", ac.GetName(), err) + } + } + + s.actorLogger.EmitLifecycleLog("Actor restored", req.GetActorId(), req.GetActorTemplateName(), req.GetActorTemplateNamespace()) + + return &ateompb.RestoreWorkloadResponse{}, nil +} + +func createNetNSWithoutSwitching(ctx context.Context, name string) (netns.NsHandle, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // We need to create the new NS, then switch back to the current netns. + curNetNS, err := netns.Get() + if err != nil { + return -1, fmt.Errorf("while getting current netns: %w", err) + } + defer func() { + if err := netns.Set(curNetNS); err != nil { + // Better to blow up the program than continue execution with + // one OS thread randomly in a different netns. + panic(fmt.Sprintf("Failed to restore original netns: %v", err)) + } + }() + + interiorNetNS, err := netns.NewNamed(name) + if err != nil { + return -1, fmt.Errorf("while creating interior network namespace for gVisor: %w", err) + } + + return interiorNetNS, nil +} + +func netNSDo(ctx context.Context, targetNS netns.NsHandle, do func(context.Context) error) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + // We need to create the new NS, then switch back to the current netns. + curNetNS, err := netns.Get() + if err != nil { + return fmt.Errorf("while getting current netns: %w", err) + } + defer func() { + if err := netns.Set(curNetNS); err != nil { + // Better to blow up the program than continue execution with + // one OS thread randomly in a different netns. + panic(fmt.Sprintf("Failed to restore original netns: %v", err)) + } + }() + + if err := netns.Set(targetNS); err != nil { + return fmt.Errorf("setting target netns: %w", err) + } + + if err := do(ctx); err != nil { + return fmt.Errorf("while executing function in target netns: %w", err) + } + + return nil +} + +type SaveLinkInfo struct { + Addresses []SaveAddr + Routes []SaveRoute +} + +type SaveAddr struct { + Addr net.IPNet + Scope int + Broadcast net.IP +} + +type SaveRoute struct { + Scope uint8 + Dst net.IPNet + Src net.IP + Gateway net.IP + Protocol int + Type int +} + +func scrapeLink(link netlink.Link) (*SaveLinkInfo, error) { + rawAddrs, err := netlink.AddrList(link, netlink.FAMILY_ALL) + if err != nil { + return nil, fmt.Errorf("while scraping addresses: %w", err) + } + + var addrs []SaveAddr + for _, rawAddr := range rawAddrs { + addr := SaveAddr{ + Addr: *rawAddr.IPNet, + Scope: rawAddr.Scope, + Broadcast: rawAddr.Broadcast, + } + addrs = append(addrs, addr) + } + + rawRoutes, err := netlink.RouteList(link, netlink.FAMILY_ALL) + if err != nil { + return nil, fmt.Errorf("while scraping routes: %w", err) + } + + var routes []SaveRoute + for _, rawRoute := range rawRoutes { + route := SaveRoute{ + Scope: uint8(rawRoute.Scope), + Dst: *rawRoute.Dst, + Src: rawRoute.Src, + Gateway: rawRoute.Gw, + Protocol: int(rawRoute.Protocol), + Type: rawRoute.Type, + } + routes = append(routes, route) + } + + return &SaveLinkInfo{ + Addresses: addrs, + Routes: routes, + }, nil +} + +func restoreLink(ctx context.Context, link netlink.Link, info *SaveLinkInfo) error { + for i, saveAddr := range info.Addresses { + addr := &netlink.Addr{ + IPNet: &saveAddr.Addr, + Scope: saveAddr.Scope, + Broadcast: saveAddr.Broadcast, + } + if err := netlink.AddrReplace(link, addr); err != nil { + return fmt.Errorf("while restoring addr %d onto link: %w", i, err) + } + } + for i, saveRoute := range info.Routes { + route := &netlink.Route{ + LinkIndex: link.Attrs().Index, + Scope: netlink.Scope(saveRoute.Scope), + Dst: &saveRoute.Dst, + Src: saveRoute.Src, + Gw: saveRoute.Gateway, + Protocol: netlink.RouteProtocol(saveRoute.Protocol), + Type: saveRoute.Type, + } + slog.InfoContext(ctx, "Restoring route", slog.String("dst", saveRoute.Dst.String()), slog.String("src", saveRoute.Src.String()), slog.String("gateway", saveRoute.Gateway.String())) + if err := netlink.RouteReplace(route); err != nil { + return fmt.Errorf("while restoring route %d: %w", i, err) + } + } + return nil +} + +func dumpNetInfo(ctx context.Context, prefix string) error { + links, err := netlink.LinkList() + if err != nil { + return fmt.Errorf("in netlink.LinkList(): %w", err) + } + + for _, link := range links { + slog.InfoContext(ctx, prefix+"Link", slog.String("name", link.Attrs().Name), slog.String("type", link.Type()), slog.Any("attrs", link.Attrs())) + + addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) + if err != nil { + return fmt.Errorf("while getting pod eth0 addresses: %w", err) + } + slog.InfoContext(ctx, prefix+"Link Addresses", slog.String("link", link.Attrs().Name), slog.Any("addrs", addrs)) + + rts, err := netlink.RouteList(link, netlink.FAMILY_V4) + if err != nil { + return fmt.Errorf("while getting routes off eth0: %w", err) + } + for _, rt := range rts { + slog.InfoContext(ctx, prefix+"Link Routes", slog.Any("link", link.Attrs().Name), slog.Any("route", rt), slog.Any("route-string", rt.String())) + } + } + + return nil +} diff --git a/cmd/servers/ateom-gvisor/logger.go b/cmd/servers/ateom-gvisor/logger.go new file mode 100644 index 000000000..195d60875 --- /dev/null +++ b/cmd/servers/ateom-gvisor/logger.go @@ -0,0 +1,141 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bufio" + "context" + "encoding/json" + "io" + "log/slog" + "os" + "strings" +) + +// ActorLogger handles structured logging for actor sandboxes and lifecycle events. +type ActorLogger struct { + logger *slog.Logger + labelsKey string + writer io.Writer +} + +// NewActorLogger creates a new ActorLogger wrapping the provided destination writer. +func NewActorLogger(w io.Writer, isOnGCE bool) *ActorLogger { + labelsKey := "labels" + if isOnGCE { + labelsKey = "logging.googleapis.com/labels" + } + return &ActorLogger{ + logger: slog.New(slog.NewJSONHandler(w, nil)), + labelsKey: labelsKey, + writer: w, + } +} + +// EmitLifecycleLog logs a synthetic actor lifecycle event. +func (al *ActorLogger) EmitLifecycleLog(msg, actorID, actorTemplate, actorNamespace string) { + al.logger.LogAttrs(context.Background(), slog.LevelInfo, msg, + slog.Group(al.labelsKey, + slog.String("ate.dev/actor_id", actorID), + slog.String("ate.dev/actor_template", actorTemplate), + slog.String("ate.dev/actor_namespace", actorNamespace), + ), + ) +} + +// StartJSONLogPipe intercepts container raw stdout/stderr streams and pipes them through the logger. +func (al *ActorLogger) StartJSONLogPipe(actorID, actorTemplate, actorNamespace string) (io.WriteCloser, error) { + pr, pw, err := os.Pipe() + if err != nil { + return nil, err + } + go func() { + al.WrapContainerLogs(pr, actorID, actorTemplate, actorNamespace) + pr.Close() + }() + return pw, nil +} + +// WrapContainerLogs reads log lines from r, parses them, and logs them in a unified structured format. +func (al *ActorLogger) WrapContainerLogs(r io.Reader, actorID, actorTemplate, actorNamespace string) { + ctx := context.Background() + rdr := bufio.NewReader(r) + for { + lineBytes, err := rdr.ReadBytes('\n') + + // Strip trailing newline from ReadBytes if present + if len(lineBytes) > 0 && lineBytes[len(lineBytes)-1] == '\n' { + lineBytes = lineBytes[:len(lineBytes)-1] + } + + if len(lineBytes) > 0 { + var m map[string]any + if unmarshalErr := json.Unmarshal(lineBytes, &m); unmarshalErr != nil { + al.logger.LogAttrs(ctx, slog.LevelInfo, string(lineBytes), + slog.Group(al.labelsKey, + slog.String("ate.dev/actor_id", actorID), + slog.String("ate.dev/actor_template", actorTemplate), + slog.String("ate.dev/actor_namespace", actorNamespace), + ), + ) + } else { + al.parseAndLogContainerJSONLine(ctx, m, actorID, actorTemplate, actorNamespace) + } + } + + if err != nil { + break + } + } +} + +func (al *ActorLogger) parseAndLogContainerJSONLine(ctx context.Context, m map[string]any, actorID, actorTemplate, actorNamespace string) { + msg := "" + if mMsg, ok := m["msg"].(string); ok { + msg = mMsg + } else if mMessage, ok := m["message"].(string); ok { + msg = mMessage + } + + level := slog.LevelInfo + if mLevel, ok := m["level"].(string); ok { + switch strings.ToLower(mLevel) { + case "debug": + level = slog.LevelDebug + case "info": + level = slog.LevelInfo + case "warn", "warning": + level = slog.LevelWarn + case "error": + level = slog.LevelError + } + } + + var attrs []slog.Attr + for k, v := range m { + if k == "msg" || k == "message" || k == "level" || k == "time" { + continue + } + attrs = append(attrs, slog.Any(k, v)) + } + + attrs = append(attrs, slog.Group(al.labelsKey, + slog.String("ate.dev/actor_id", actorID), + slog.String("ate.dev/actor_template", actorTemplate), + slog.String("ate.dev/actor_namespace", actorNamespace), + )) + + al.logger.LogAttrs(ctx, level, msg, attrs...) +} diff --git a/cmd/servers/ateom-gvisor/logger_test.go b/cmd/servers/ateom-gvisor/logger_test.go new file mode 100644 index 000000000..abd742806 --- /dev/null +++ b/cmd/servers/ateom-gvisor/logger_test.go @@ -0,0 +1,99 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "encoding/json" + "strings" + "testing" +) + +func TestWrapContainerLogs(t *testing.T) { + input := "Test application log output\n" + rdr := strings.NewReader(input) + var buf bytes.Buffer + + al := NewActorLogger(&buf, false) + al.WrapContainerLogs(rdr, "act-1", "tmpl-1", "default") + + var m map[string]any + if err := json.Unmarshal(buf.Bytes(), &m); err != nil { + t.Fatalf("failed to parse JSON output: %v", err) + } + + if m["msg"] != "Test application log output" { + t.Errorf("got msg = %v, want 'Test application log output'", m["msg"]) + } + if m["level"] != "INFO" { + t.Errorf("got level = %v, want 'INFO'", m["level"]) + } + + labelsAny, ok := m[al.labelsKey] + if !ok { + t.Fatal("missing labels group") + } + labels, ok := labelsAny.(map[string]any) + if !ok { + t.Fatal("labels group is not a map") + } + + if labels["ate.dev/actor_id"] != "act-1" { + t.Errorf("got actor_id = %v, want 'act-1'", labels["ate.dev/actor_id"]) + } + if labels["ate.dev/actor_template"] != "tmpl-1" { + t.Errorf("got actor_template = %v, want 'tmpl-1'", labels["ate.dev/actor_template"]) + } + if labels["ate.dev/actor_namespace"] != "default" { + t.Errorf("got actor_namespace = %v, want 'default'", labels["ate.dev/actor_namespace"]) + } +} + +func TestWrapContainerLogs_JSONInput(t *testing.T) { + input := `{"level":"info","msg":"Started container","custom_attr":"value"}` + "\n" + rdr := strings.NewReader(input) + var buf bytes.Buffer + + al := NewActorLogger(&buf, false) + al.WrapContainerLogs(rdr, "act-1", "tmpl-1", "default") + + var m map[string]any + if err := json.Unmarshal(buf.Bytes(), &m); err != nil { + t.Fatalf("failed to parse JSON output: %v", err) + } + + if m["msg"] != "Started container" { + t.Errorf("got msg = %v, want 'Started container'", m["msg"]) + } + if m["level"] != "INFO" { + t.Errorf("got level = %v, want 'INFO'", m["level"]) + } + if m["custom_attr"] != "value" { + t.Errorf("got custom_attr = %v, want 'value'", m["custom_attr"]) + } + + labelsAny, ok := m[al.labelsKey] + if !ok { + t.Fatal("missing labels group") + } + labels, ok := labelsAny.(map[string]any) + if !ok { + t.Fatal("labels group is not a map") + } + + if labels["ate.dev/actor_id"] != "act-1" { + t.Errorf("got actor_id = %v, want 'act-1'", labels["ate.dev/actor_id"]) + } +} diff --git a/cmd/servers/ateom-gvisor/runsc.go b/cmd/servers/ateom-gvisor/runsc.go new file mode 100644 index 000000000..6db499a54 --- /dev/null +++ b/cmd/servers/ateom-gvisor/runsc.go @@ -0,0 +1,234 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "fmt" + "io" + "log/slog" + "os" + "os/exec" + + "github.com/agent-substrate/substrate/internal/ateompath" +) + +type runsc struct { + path string + actorTemplateNamespace string + actorTemplateName string + actorID string +} + +func (r *runsc) cmdCreate(ctx context.Context, out io.Writer, containerName string) error { + reapLock.RLock() + defer reapLock.RUnlock() + + slog.InfoContext(ctx, "About to run runsc create", slog.String("container", containerName)) + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + // "-debug", + // "-debug-log", ateompath.RunscDebugLogDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName)+"/", + // "-debug-to-user-log", + // "-log-packets", + // "-strace", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "create", + "-bundle", ateompath.OCIBundlePath(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName), + "-pid-file", ateompath.PIDFilePath(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName), + containerName, // Name of the container + ) + cmd.Stdout = out + cmd.Stderr = out + + err := cmd.Run() + if err != nil { + return fmt.Errorf("while running `runsc create`: %w", err) + } + + return nil +} + +func (r *runsc) cmdStart(ctx context.Context, out io.Writer, containerName string) error { + reapLock.RLock() + defer reapLock.RUnlock() + + slog.InfoContext(ctx, "About to run runsc start", slog.String("container", containerName)) + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + // "-debug", + // "-debug-log", ateompath.RunscDebugLogDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName)+"/", + // "-debug-to-user-log", + // "-log-packets", + // "-strace", + "-allow-connected-on-save", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "start", + containerName, // Name of the container + ) + cmd.Stdout = out + cmd.Stderr = out + + err := cmd.Run() + if err != nil { + return fmt.Errorf("while running `runsc start`: %w", err) + } + + return nil +} + +func (r *runsc) cmdCheckpoint(ctx context.Context, containerName, checkpointPath string) error { + reapLock.RLock() + defer reapLock.RUnlock() + + slog.InfoContext(ctx, "About to run runsc checkpoint", slog.String("container", containerName)) + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + // "-debug", + // "-debug-log", ateompath.RunscDebugLogDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName)+"/", + // "-debug-to-user-log", + // "-log-packets", + // "-strace", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "checkpoint", + "-image-path", checkpointPath, + containerName, // Name of the container + ) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + return fmt.Errorf("while running `runsc checkpoint`: %w", err) + } + return nil +} + +// We take a checkpoint only of the root container of the sandbox, but we need +// to call restore on each container, using the same checkpoint. +func (r *runsc) cmdRestore(ctx context.Context, out io.Writer, containerName, checkpointPath string) error { + reapLock.RLock() + defer reapLock.RUnlock() + + slog.InfoContext(ctx, "About to run runsc restore", slog.String("container", containerName)) + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + // "-debug", + // "-debug-log", ateompath.RunscDebugLogDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName)+"/", + // "-debug-to-user-log", + // "-log-packets", + // "-strace", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "restore", + "-bundle", ateompath.OCIBundlePath(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName), + "-image-path", checkpointPath, + "-pid-file", ateompath.PIDFilePath(r.actorTemplateNamespace, r.actorTemplateName, r.actorID, containerName), + //"-background", + //"-direct", // TODO(ateom): Reenable direct + "-detach", + containerName, + ) + cmd.Stdout = out + cmd.Stderr = out + if err := cmd.Run(); err != nil { + return fmt.Errorf("while running `runsc restore`: %w", err) + } + return nil +} + +func (r *runsc) cmdDelete(ctx context.Context, containerName string) error { + reapLock.RLock() + defer reapLock.RUnlock() + + // token := rand.Text() + // logFile := "/tmp/runsc.delete." + token + ".log" + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + // "-debug", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "delete", + "-force", + containerName, + ) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err := cmd.Run() + if err != nil { + return fmt.Errorf("while running `runsc delete`: %w", err) + } + + return nil +} + +func (r *runsc) cmdState(ctx context.Context, containerName string) error { + reapLock.RLock() + defer reapLock.RUnlock() + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "state", + containerName, + ) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("while running `runsc state`: %w", err) + } + return nil +} + +func (r *runsc) cmdList(ctx context.Context) error { + reapLock.RLock() + defer reapLock.RUnlock() + + cmd := exec.CommandContext( + ctx, + r.path, + "-log-format", "json", + "--alsologtostderr", + "-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID), + "list", + ) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("while running `runsc list`: %w", err) + } + return nil +} diff --git a/cmd/servers/ateom-gvisor/stopwatch.go b/cmd/servers/ateom-gvisor/stopwatch.go new file mode 100644 index 000000000..64304c59e --- /dev/null +++ b/cmd/servers/ateom-gvisor/stopwatch.go @@ -0,0 +1,64 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "log/slog" + "time" +) + +type Lap struct { + Name string + Time time.Time + StepDuration time.Duration + TotalDuration time.Duration +} + +type Stopwatch struct { + Laps []Lap +} + +var _ slog.LogValuer = (*Stopwatch)(nil) + +func (s *Stopwatch) Click(name string) { + now := time.Now() + lap := Lap{ + Name: name, + Time: now, + } + if len(s.Laps) > 0 { + lap.StepDuration = now.Sub(s.Laps[len(s.Laps)-1].Time) + lap.TotalDuration = now.Sub(s.Laps[0].Time) + } + s.Laps = append(s.Laps, lap) +} + +type FormattedLap struct { + Name string + Step string + Total string +} + +func (s *Stopwatch) LogValue() slog.Value { + formatted := []FormattedLap{} + for _, l := range s.Laps { + formatted = append(formatted, FormattedLap{ + Name: l.Name, + Step: l.StepDuration.String(), + Total: l.TotalDuration.String(), + }) + } + return slog.AnyValue(formatted) +} diff --git a/cmd/servers/podcertcontroller/podcertcontroller.go b/cmd/servers/podcertcontroller/podcertcontroller.go new file mode 100644 index 000000000..7932fd277 --- /dev/null +++ b/cmd/servers/podcertcontroller/podcertcontroller.go @@ -0,0 +1,149 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Command podcertcontroller is a pod certificate controller that implements two signers. +// - servicedns.ate.dev/identity: Issues certificate for Kubernetes service DNS names, backed by a +// local CA. +// - podid.ate.dev/identity: Issues certificates equivalent to KSA tokens, backed by a local CA. +// +// These signers are not unique to Agent Substrate, and will eventually be replaced by signers that +// are being developed as part of upstream Kubernetes. +package main + +import ( + "context" + "flag" + "log/slog" + "os" + "os/signal" + "path/filepath" + "syscall" + + "github.com/agent-substrate/substrate/internal/localca" + "github.com/agent-substrate/substrate/internal/podidentitysigner" + "github.com/agent-substrate/substrate/internal/rendezvous" + "github.com/agent-substrate/substrate/internal/servicednssigner" + "github.com/agent-substrate/substrate/internal/signercontroller" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" + "k8s.io/utils/clock" +) + +var kubeConfigDefault string + +func init() { + if home := homedir.HomeDir(); home != "" { + kubeConfigDefault = filepath.Join(home, ".kube", "config") + } +} + +var ( + kubeconfig = flag.String("kubeconfig", kubeConfigDefault, "absolute path to the kubeconfig file") + inCluster = flag.Bool("in-cluster", false, "Is the controller running in the cluster it should connect to?") + + shardingNamespace = flag.String("sharding-pod-namespace", "", "(Work Sharding) The namespace the controller is running in") + shardingPodName = flag.String("sharding-pod-name", "", "(Work Sharding) The pod name of the controller") + shardingPodUID = flag.String("sharding-pod-uid", "", "(Work Sharding) The pod UID of the controller") + shardingApplicationName = flag.String("sharding-application-name", "", "(Work Sharding) The application name to disambiguate Leases") + + serviceDNSCAPoolFile = flag.String( + "service-dns-ca-pool", + "", + "File that contains the CA pool state for "+servicednssigner.Name, + ) + + podCAPoolFile = flag.String( + "pod-identity-ca-pool", + "", + "File that contains the CA pool state for "+podidentitysigner.Name, + ) +) + +func main() { + ctx := context.Background() + + flag.Parse() + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil))) + + var kconfig *rest.Config + var err error + if *inCluster { + kconfig, err = rest.InClusterConfig() + if err != nil { + slog.ErrorContext(ctx, "Error creating in-cluster config", slog.Any("err", err)) + os.Exit(1) + } + } else { + // use the current context in kubeconfig + kconfig, err = clientcmd.BuildConfigFromFlags("", *kubeconfig) + if err != nil { + slog.ErrorContext(ctx, "Error reading kubeconfig", slog.Any("err", err)) + os.Exit(1) + } + } + + kc, err := kubernetes.NewForConfig(kconfig) + if err != nil { + slog.ErrorContext(ctx, "Error creating Kubernetes client", slog.Any("err", err)) + os.Exit(1) + } + + hasher := rendezvous.New( + kc, + *shardingNamespace, + *shardingApplicationName, + *shardingPodName, + types.UID(*shardingPodUID), + clock.RealClock{}, + ) + go hasher.Run(ctx) + + // Create a signer for servicedns.ate.dev/identity + serviceDNSCAPoolBytes, err := os.ReadFile(*serviceDNSCAPoolFile) + if err != nil { + slog.ErrorContext(ctx, "Error reading servicedns.ate.dev/identity CA pool state", slog.Any("err", err)) + os.Exit(1) + } + serviceDNSCAPool, err := localca.Unmarshal(serviceDNSCAPoolBytes) + if err != nil { + slog.ErrorContext(ctx, "Error unmarshing servicedns.ate.dev/identity CA pool state", slog.Any("err", err)) + os.Exit(1) + } + serviceDNSSignerController := signercontroller.New(clock.RealClock{}, servicednssigner.NewImpl(kc, serviceDNSCAPool, clock.RealClock{}), kc, hasher) + go serviceDNSSignerController.Run(ctx) + + // Create a signer for podidentity.podcert.ate.dev/identity + podIdentityCAPoolBytes, err := os.ReadFile(*podCAPoolFile) + if err != nil { + slog.ErrorContext(ctx, "Error reading podidentity.podcert.ate.dev/identity CA pool state", slog.Any("err", err)) + os.Exit(1) + } + podIdentityCAPool, err := localca.Unmarshal(podIdentityCAPoolBytes) + if err != nil { + slog.ErrorContext(ctx, "Error unmarshing podidentity.podcert.ate.dev/identity CA pool state", slog.Any("err", err)) + os.Exit(1) + } + podIdentitySignerController := signercontroller.New(clock.RealClock{}, podidentitysigner.NewImpl(kc, podIdentityCAPool, clock.RealClock{}), kc, hasher) + go podIdentitySignerController.Run(ctx) + + // TODO: Reload when the file changes. + + signalCh := make(chan os.Signal, 1) + signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM) + + <-signalCh +} diff --git a/cmd/setup/cmd/api.go b/cmd/setup/cmd/api.go new file mode 100644 index 000000000..f0a0eeb10 --- /dev/null +++ b/cmd/setup/cmd/api.go @@ -0,0 +1,60 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "context" + "fmt" + "log/slog" + "strings" + + serviceusage "cloud.google.com/go/serviceusage/apiv1" + "cloud.google.com/go/serviceusage/apiv1/serviceusagepb" +) + +func enableRequiredAPIs(ctx context.Context, env *Environment) error { + suClient, err := serviceusage.NewClient(ctx) + if err != nil { + return err + } + defer suClient.Close() + + services := []string{ + "cloudresourcemanager.googleapis.com", + "container.googleapis.com", + "networkconnectivity.googleapis.com", + "serviceusage.googleapis.com", + "storage.googleapis.com", + } + + slog.Info("Batch enabling services", slog.String("services", strings.Join(services, ", "))) + + req := &serviceusagepb.BatchEnableServicesRequest{ + Parent: fmt.Sprintf("projects/%s", env.ProjectID), + ServiceIds: services, + } + + op, err := suClient.BatchEnableServices(ctx, req) + if err != nil { + return fmt.Errorf("failed to start batch enabling services: %w", err) + } + + if _, err := op.Wait(ctx); err != nil { + return fmt.Errorf("failed to complete batch enabling services: %w", err) + } + + slog.Info("Successfully enabled required services.") + return nil +} diff --git a/cmd/setup/cmd/bucket.go b/cmd/setup/cmd/bucket.go new file mode 100644 index 000000000..65e036a38 --- /dev/null +++ b/cmd/setup/cmd/bucket.go @@ -0,0 +1,139 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "context" + "errors" + "fmt" + "log/slog" + "slices" + "strconv" + "strings" + + "cloud.google.com/go/iam" + "cloud.google.com/go/storage" +) + +func createSnapshotBucket(ctx context.Context, env *Environment) error { + client, err := storage.NewClient(ctx) + if err != nil { + return err + } + defer client.Close() + + bucket := client.Bucket(env.BucketName) + slog.Info("Checking if Bucket exists", slog.String("bucket", env.BucketName)) + attrs, err := bucket.Attrs(ctx) + if err != nil { + if !errors.Is(err, storage.ErrBucketNotExist) { + return fmt.Errorf("getting bucket: %w", err) + } + + slog.Info("Bucket does not exist. Creating...", slog.String("bucket", env.BucketName)) + err = bucket.Create(ctx, env.ProjectID, &storage.BucketAttrs{ + Location: env.GCERegion, + UniformBucketLevelAccess: storage.UniformBucketLevelAccess{ + Enabled: true, + }, + }) + if err != nil { + return fmt.Errorf("create snapshot bucket: %w", err) + } + return nil + } + + slog.Info("Bucket exists. Checking attributes...", slog.String("bucket", env.BucketName)) + + // Ensure the bucket belongs to the correct project. + // GCS bucket names are globally unique, so it's possible this bucket belongs to a different project. + projectNum := strconv.FormatUint(attrs.ProjectNumber, 10) + if projectNum != env.ProjectNumber { + return fmt.Errorf("bucket %s belongs to project number %s, but expected %s (it may be owned by another GCP project)", env.BucketName, projectNum, env.ProjectNumber) + } + + // Ensure the bucket is in the correct region. + if !strings.EqualFold(attrs.Location, env.GCERegion) { + return fmt.Errorf("bucket %s is in location %s, but expected %s", env.BucketName, attrs.Location, env.GCERegion) + } + + slog.Info("Bucket is in the correct project and region. Checking uniform-bucket-level-access setting...", slog.String("bucket", env.BucketName)) + if !attrs.UniformBucketLevelAccess.Enabled { + slog.Info("Updating uniform-bucket-level-access", slog.String("bucket", env.BucketName)) + _, err = bucket.Update(ctx, storage.BucketAttrsToUpdate{ + UniformBucketLevelAccess: &storage.UniformBucketLevelAccess{ + Enabled: true, + }, + }) + if err != nil { + return fmt.Errorf("update bucket ubla: %w", err) + } + } else { + slog.Info("uniform-bucket-level-access is already correct", slog.String("bucket", env.BucketName)) + } + + return nil +} + +func createIamPolicyBindings(ctx context.Context, env *Environment) error { + client, err := storage.NewClient(ctx) + if err != nil { + return err + } + defer client.Close() + + bucket := client.Bucket(env.BucketName) + policy, err := bucket.IAM().Policy(ctx) + if err != nil { + return fmt.Errorf("get bucket iam policy: %w", err) + } + + member := fmt.Sprintf("principal://iam.googleapis.com/projects/%s/locations/global/workloadIdentityPools/%s.svc.id.goog/subject/ns/ate-system/sa/atelet", env.ProjectNumber, env.ProjectID) + + hasStorageAdmin := false + hasBucketViewer := false + for _, b := range policy.InternalProto.Bindings { + if b.Condition != nil { + continue + } + if b.Role == "roles/storage.objectAdmin" && slices.Contains(b.Members, member) { + hasStorageAdmin = true + } + if b.Role == "roles/storage.bucketViewer" && slices.Contains(b.Members, member) { + hasBucketViewer = true + } + if hasStorageAdmin && hasBucketViewer { + slog.Info("IAM policy is already correct", slog.String("bucket", env.BucketName), slog.String("member", member)) + return nil + } + } + + if !hasStorageAdmin { + slog.Info("Adding storage.objectAdmin role to member", slog.String("bucket", env.BucketName), slog.String("member", member)) + policy.Add(member, iam.RoleName("roles/storage.objectAdmin")) + } + if !hasBucketViewer { + slog.Info("Adding storage.bucketViewer role to member", slog.String("bucket", env.BucketName), slog.String("member", member)) + policy.Add(member, iam.RoleName("roles/storage.bucketViewer")) + } + + slog.Info("Setting IAM policy for bucket", slog.String("bucket", env.BucketName)) + err = bucket.IAM().SetPolicy(ctx, policy) + if err != nil { + return fmt.Errorf("set bucket iam policy: %w", err) + } + + return nil +} diff --git a/cmd/setup/cmd/cluster.go b/cmd/setup/cmd/cluster.go new file mode 100644 index 000000000..acfd153c9 --- /dev/null +++ b/cmd/setup/cmd/cluster.go @@ -0,0 +1,233 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "context" + "fmt" + "log/slog" + "slices" + "strings" + "time" + + container "cloud.google.com/go/container/apiv1" + "cloud.google.com/go/container/apiv1/containerpb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "k8s.io/apimachinery/pkg/util/wait" +) + +var requiredBetaAPIs = []string{ + "certificates.k8s.io/v1beta1/podcertificaterequests", + "certificates.k8s.io/v1beta1/clustertrustbundles", +} + +func deleteCluster(ctx context.Context, env *Environment) error { + client, err := container.NewClusterManagerClient(ctx) + if err != nil { + return err + } + defer client.Close() + name := fmt.Sprintf("projects/%s/locations/%s/clusters/%s", env.ProjectID, env.ClusterLocation, env.ClusterName) + slog.Info("Deleting cluster", slog.String("cluster", env.ClusterName)) + op, err := client.DeleteCluster(ctx, &containerpb.DeleteClusterRequest{Name: name}) + if err != nil { + return fmt.Errorf("delete cluster: %w", err) + } + return waitContainerOperation(ctx, client, op.Name, env) +} + +func createClusterInternal(ctx context.Context, env *Environment, client *container.ClusterManagerClient, parent string) error { + slog.Info("Cluster does not exist. Creating...", slog.String("cluster", env.ClusterName)) + req := &containerpb.CreateClusterRequest{ + Parent: parent, + Cluster: &containerpb.Cluster{ + Name: env.ClusterName, + InitialClusterVersion: env.ClusterVersion, + NodePools: []*containerpb.NodePool{ + { + Name: "substrate-node-pool", + InitialNodeCount: 2, + Config: &containerpb.NodeConfig{ + MachineType: env.GVisorNodeMachineType, + }, + }, + }, + EnableK8SBetaApis: &containerpb.K8SBetaAPIConfig{ + EnabledApis: requiredBetaAPIs, + }, + WorkloadIdentityConfig: &containerpb.WorkloadIdentityConfig{ + WorkloadPool: fmt.Sprintf("%s.svc.id.goog", env.ProjectID), + }, + Network: env.Network, + Subnetwork: env.Subnetwork, + }, + } + op, err := client.CreateCluster(ctx, req) + if err != nil { + return fmt.Errorf("create cluster: %w", err) + } + return waitContainerOperation(ctx, client, op.Name, env) +} + +func createClusterIdempotent(ctx context.Context, env *Environment) error { + client, err := container.NewClusterManagerClient(ctx) + if err != nil { + return err + } + defer client.Close() + + parent := fmt.Sprintf("projects/%s/locations/%s", env.ProjectID, env.ClusterLocation) + clusterName := fmt.Sprintf("projects/%s/locations/%s/clusters/%s", env.ProjectID, env.ClusterLocation, env.ClusterName) + + slog.Info("Checking if cluster exists", slog.String("cluster", env.ClusterName), slog.String("location", env.ClusterLocation)) + cluster, err := client.GetCluster(ctx, &containerpb.GetClusterRequest{Name: clusterName}) + if err != nil { + if status.Code(err) != codes.NotFound { + return fmt.Errorf("getting cluster: %w", err) + } + + return createClusterInternal(ctx, env, client, parent) + } + + slog.Info("Cluster exists. Checking attributes...", slog.String("cluster", env.ClusterName)) + + // Recreate cluster if network configuration mismatches. + expectedNetwork := fmt.Sprintf("projects/%s/global/networks/%s", env.ProjectID, env.Network) + if cluster.NetworkConfig != nil && cluster.NetworkConfig.Network != "" && !strings.HasSuffix(cluster.NetworkConfig.Network, expectedNetwork) { + slog.Info("Mismatch in network", slog.String("current", cluster.NetworkConfig.Network), slog.String("expected", expectedNetwork)) + if err := deleteCluster(ctx, env); err != nil { + return err + } + return createClusterInternal(ctx, env, client, parent) + } + + // Recreate cluster if subnet configuration mismatches. + expectedSubnetwork := fmt.Sprintf("projects/%s/regions/%s/subnetworks/%s", env.ProjectID, env.GCERegion, env.Subnetwork) + if cluster.NetworkConfig != nil && cluster.NetworkConfig.Subnetwork != "" && !strings.HasSuffix(cluster.NetworkConfig.Subnetwork, expectedSubnetwork) { + slog.Info("Mismatch in subnetwork", slog.String("current", cluster.NetworkConfig.Subnetwork), slog.String("expected", expectedSubnetwork)) + if err := deleteCluster(ctx, env); err != nil { + return err + } + return createClusterInternal(ctx, env, client, parent) + } + + expectedWorkloadPool := fmt.Sprintf("%s.svc.id.goog", env.ProjectID) + currentWorkloadPool := "" + if cluster.WorkloadIdentityConfig != nil { + currentWorkloadPool = cluster.WorkloadIdentityConfig.WorkloadPool + } + if currentWorkloadPool != expectedWorkloadPool { + slog.Info("Mismatch in workload pool", slog.String("current", currentWorkloadPool), slog.String("expected", expectedWorkloadPool)) + slog.Info("Updating cluster WorkloadIdentityConfig...") + op, err := client.UpdateCluster(ctx, &containerpb.UpdateClusterRequest{ + Name: clusterName, + Update: &containerpb.ClusterUpdate{ + DesiredWorkloadIdentityConfig: &containerpb.WorkloadIdentityConfig{ + WorkloadPool: expectedWorkloadPool, + }, + }, + }) + if err != nil { + return fmt.Errorf("update cluster workload identity: %w", err) + } + if err := waitContainerOperation(ctx, client, op.Name, env); err != nil { + return err + } + } else { + slog.Info("Cluster WorkloadIdentityConfig match perfectly.", slog.String("cluster", env.ClusterName)) + } + + if cluster.EnableK8SBetaApis == nil || + len(cluster.EnableK8SBetaApis.EnabledApis) == 0 || + !containsAll(cluster.EnableK8SBetaApis.EnabledApis, requiredBetaAPIs) { + + clusterEnabledAPIs := []string{} + if cluster.EnableK8SBetaApis != nil && len(cluster.EnableK8SBetaApis.EnabledApis) > 0 { + clusterEnabledAPIs = cluster.EnableK8SBetaApis.EnabledApis + } + slog.Info("Mismatch in EnableK8SBetaApis", slog.String("current", strings.Join(clusterEnabledAPIs, ",")), slog.String("expected", strings.Join(requiredBetaAPIs, ","))) + + var combinedAPIs []string + for _, api := range append(requiredBetaAPIs, clusterEnabledAPIs...) { + if !slices.Contains(combinedAPIs, api) { + combinedAPIs = append(combinedAPIs, api) + } + } + + op, err := client.UpdateCluster(ctx, &containerpb.UpdateClusterRequest{ + Name: clusterName, + Update: &containerpb.ClusterUpdate{ + DesiredK8SBetaApis: &containerpb.K8SBetaAPIConfig{ + EnabledApis: combinedAPIs, + }, + }, + }) + if err != nil { + return fmt.Errorf("update cluster beta apis: %w", err) + } + if err := waitContainerOperation(ctx, client, op.Name, env); err != nil { + return err + } + } else { + slog.Info("Cluster EnableK8SBetaApis match perfectly.", slog.String("cluster", env.ClusterName)) + } + + return nil +} + +func waitContainerOperation(ctx context.Context, client *container.ClusterManagerClient, opName string, env *Environment) error { + slog.Info("Waiting for operation to complete...", slog.String("operation", opName)) + + fullName := opName + if !strings.HasPrefix(opName, "projects/") { + fullName = fmt.Sprintf("projects/%s/locations/%s/operations/%s", env.ProjectID, env.ClusterLocation, opName) + } + + err := wait.PollUntilContextTimeout(ctx, 10*time.Second, 30*time.Minute, true, func(pollCtx context.Context) (bool, error) { + op, err := client.GetOperation(pollCtx, &containerpb.GetOperationRequest{ + Name: fullName, + }) + if err != nil { + return false, fmt.Errorf("failed to get operation status: %w", err) + } + if op.Status == containerpb.Operation_DONE { + if op.Error != nil { + return true, fmt.Errorf("operation failed: %v", op.Error) + } + slog.Info("Operation completed successfully.", slog.String("operation", opName)) + return true, nil + } + if op.Status == containerpb.Operation_ABORTING { + return true, fmt.Errorf("operation %s is aborting", opName) + } + return false, nil + }) + + if err != nil { + return fmt.Errorf("wait for operation %s: %w", opName, err) + } + + return nil +} + +func containsAll(clusterAPIs []string, requiredAPIs []string) bool { + for _, s := range requiredAPIs { + if !slices.Contains(clusterAPIs, s) { + return false + } + } + return true +} diff --git a/cmd/setup/cmd/common.go b/cmd/setup/cmd/common.go new file mode 100644 index 000000000..79be17df9 --- /dev/null +++ b/cmd/setup/cmd/common.go @@ -0,0 +1,78 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + "strings" +) + +type Environment struct { + ProjectID string + ProjectNumber string + ClusterName string + ClusterLocation string + ClusterVersion string + Network string + Subnetwork string + NodePoolName string + NodePoolVersion string + GCERegion string + BucketName string + GVisorNodeMachineType string +} + +func loadEnv() (*Environment, error) { + requiredEnvVars := []string{ + "PROJECT_ID", + "PROJECT_NUMBER", + "CLUSTER_NAME", + "CLUSTER_LOCATION", + "CLUSTER_VERSION", + "NETWORK", + "SUBNETWORK", + "NODE_POOL_NAME", + "NODE_POOL_VERSION", + "GCE_REGION", + "BUCKET_NAME", + "GVISOR_NODE_MACHINE_TYPE", + } + + missing := []string{} + for _, key := range requiredEnvVars { + if os.Getenv(key) == "" { + missing = append(missing, key) + } + } + if len(missing) > 0 { + return nil, fmt.Errorf("missing required environment variables: %s", strings.Join(missing, ", ")) + } + + return &Environment{ + ProjectID: os.Getenv("PROJECT_ID"), + ProjectNumber: os.Getenv("PROJECT_NUMBER"), + ClusterName: os.Getenv("CLUSTER_NAME"), + ClusterLocation: os.Getenv("CLUSTER_LOCATION"), + ClusterVersion: os.Getenv("CLUSTER_VERSION"), + Network: os.Getenv("NETWORK"), + Subnetwork: os.Getenv("SUBNETWORK"), + NodePoolName: os.Getenv("NODE_POOL_NAME"), + NodePoolVersion: os.Getenv("NODE_POOL_VERSION"), + GCERegion: os.Getenv("GCE_REGION"), + BucketName: os.Getenv("BUCKET_NAME"), + GVisorNodeMachineType: os.Getenv("GVISOR_NODE_MACHINE_TYPE"), + }, nil +} diff --git a/cmd/setup/cmd/iam.go b/cmd/setup/cmd/iam.go new file mode 100644 index 000000000..19928f9fb --- /dev/null +++ b/cmd/setup/cmd/iam.go @@ -0,0 +1,131 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "context" + "fmt" + "log/slog" + "slices" + + "cloud.google.com/go/iam/apiv1/iampb" + resourcemanager "cloud.google.com/go/resourcemanager/apiv3" +) + +func addProjectIamBinding(policy *iampb.Policy, role, member string) bool { + for _, b := range policy.Bindings { + // Skip if the policy has any conditions. + if b.Condition != nil { + continue + } + if b.Role == role { + if slices.Contains(b.Members, member) { + return false // Member already has this role + } + b.Members = append(b.Members, member) + return true + } + } + // Role not found, add a new binding + policy.Bindings = append(policy.Bindings, &iampb.Binding{ + Role: role, + Members: []string{member}, + }) + return true +} + +func grantGkeNodePermissions(ctx context.Context, env *Environment) error { + client, err := resourcemanager.NewProjectsClient(ctx) + if err != nil { + return err + } + defer client.Close() + + resource := fmt.Sprintf("projects/%s", env.ProjectID) + req := &iampb.GetIamPolicyRequest{ + Resource: resource, + } + + policy, err := client.GetIamPolicy(ctx, req) + if err != nil { + return fmt.Errorf("get project iam policy: %w", err) + } + + // TODO(#76): Use a least-privileged node service account instead. + member := fmt.Sprintf("serviceAccount:%s-compute@developer.gserviceaccount.com", env.ProjectNumber) + + // TODO: Don't grant these permissions at project level. + changed1 := addProjectIamBinding(policy, "roles/storage.objectViewer", member) + changed2 := addProjectIamBinding(policy, "roles/artifactregistry.reader", member) + + if !changed1 && !changed2 { + slog.Info("IAM policy already has required GKE node permissions. Skipping update.", slog.String("project", env.ProjectID)) + return nil + } + + slog.Info("Setting IAM policy (grant gke node permissions)...", slog.String("project", env.ProjectID)) + setReq := &iampb.SetIamPolicyRequest{ + Resource: resource, + Policy: policy, + } + _, err = client.SetIamPolicy(ctx, setReq) + if err != nil { + return fmt.Errorf("set project iam policy: %w", err) + } + + return nil +} +func grantAteletPermissions(ctx context.Context, env *Environment) error { + client, err := resourcemanager.NewProjectsClient(ctx) + if err != nil { + return err + } + defer client.Close() + + resource := fmt.Sprintf("projects/%s", env.ProjectID) + req := &iampb.GetIamPolicyRequest{ + Resource: resource, + } + + policy, err := client.GetIamPolicy(ctx, req) + if err != nil { + return fmt.Errorf("get project iam policy: %w", err) + } + + member := fmt.Sprintf("principal://iam.googleapis.com/projects/%s/locations/global/workloadIdentityPools/%s.svc.id.goog/subject/ns/ate-system/sa/atelet", env.ProjectNumber, env.ProjectID) + + // TODO: This shouldn't be a project-level binding. We should grant atelet + // access only to the specific bucket and artifact registry repository in + // use. + changed1 := addProjectIamBinding(policy, "roles/storage.objectAdmin", member) + changed2 := addProjectIamBinding(policy, "roles/artifactregistry.reader", member) + + if !changed1 && !changed2 { + slog.Info("IAM policy already has required GKE node permissions. Skipping update.", slog.String("project", env.ProjectID)) + return nil + } + + slog.Info("Setting IAM policy (grant api server permissions)...", slog.String("project", env.ProjectID)) + setReq := &iampb.SetIamPolicyRequest{ + Resource: resource, + Policy: policy, + } + _, err = client.SetIamPolicy(ctx, setReq) + if err != nil { + return fmt.Errorf("set project iam policy: %w", err) + } + + return nil +} diff --git a/cmd/setup/cmd/root.go b/cmd/setup/cmd/root.go new file mode 100644 index 000000000..54dc2fffc --- /dev/null +++ b/cmd/setup/cmd/root.go @@ -0,0 +1,101 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "context" + "errors" + "fmt" + + "github.com/spf13/cobra" +) + +var ( + createClusterFlag bool + createGvisorNodePoolFlag bool + createSnapshotBucketFlag bool + createIamPolicyBindingsFlag bool + grantGkeNodePermissionsFlag bool + grantAteletPermissionsFlag bool + enableApisFlag bool + allFlag bool +) + +var rootCmd = &cobra.Command{ + Use: "setup", + Short: "Setup GCP resources for Agent Substrate", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + env, err := loadEnv() + if err != nil { + return err + } + + setupTasks := []struct { + name string + flag *bool + taskFunc func(context.Context, *Environment) error + }{ + {"enable apis", &enableApisFlag, enableRequiredAPIs}, + {"create cluster", &createClusterFlag, createClusterIdempotent}, + {"create snapshot bucket", &createSnapshotBucketFlag, createSnapshotBucket}, + {"create iam policy bindings", &createIamPolicyBindingsFlag, createIamPolicyBindings}, + {"grant gke node permissions", &grantGkeNodePermissionsFlag, grantGkeNodePermissions}, + {"grant atelet permissions", &grantAteletPermissionsFlag, grantAteletPermissions}, + } + + if cmd.Flags().NFlag() == 0 { + return cmd.Help() + } + + if allFlag { + if cmd.Flags().NFlag() > 1 { + return fmt.Errorf("the --all flag cannot be used with other task-specific flags") + } + errs := []error{} + for _, task := range setupTasks { + if err := task.taskFunc(ctx, env); err != nil { + errs = append(errs, fmt.Errorf("%s: %w", task.name, err)) + } + } + return errors.Join(errs...) + } + + for _, task := range setupTasks { + if *task.flag { + if err := task.taskFunc(ctx, env); err != nil { + return fmt.Errorf("%s: %w", task.name, err) + } + } + } + + return nil + }, +} + +func Execute() error { + return rootCmd.Execute() +} + +func init() { + rootCmd.Flags().BoolVar(&createClusterFlag, "create-cluster", false, "Create GKE cluster") + rootCmd.Flags().BoolVar(&createGvisorNodePoolFlag, "create-gvisor-node-pool", false, "Create gVisor node pool") + rootCmd.Flags().BoolVar(&createSnapshotBucketFlag, "create-snapshot-bucket", false, "Create snapshot bucket") + rootCmd.Flags().BoolVar(&createIamPolicyBindingsFlag, "create-iam-policy-bindings", false, "Create IAM policy bindings for atelet") + rootCmd.Flags().BoolVar(&grantGkeNodePermissionsFlag, "grant-gke-node-permissions", false, "Grant GKE nodes permission to pull images") + rootCmd.Flags().BoolVar(&grantAteletPermissionsFlag, "grant-atelet-permissions", false, "Grant atelet permission to read/write snapshots and pull images") + rootCmd.Flags().BoolVar(&enableApisFlag, "enable-apis", false, "Enable required Google Cloud APIs") + rootCmd.Flags().BoolVar(&allFlag, "all", false, "Run all setup steps") +} diff --git a/cmd/setup/main.go b/cmd/setup/main.go new file mode 100644 index 000000000..9b59bd80a --- /dev/null +++ b/cmd/setup/main.go @@ -0,0 +1,29 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "os" + + "github.com/agent-substrate/substrate/cmd/setup/cmd" +) + +func main() { + if err := cmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/code-of-conduct.md b/code-of-conduct.md new file mode 100644 index 000000000..6070ae1cd --- /dev/null +++ b/code-of-conduct.md @@ -0,0 +1,95 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Disrespecting the community's time by sending spam or other unsolicited + commercial messages +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, +offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +This Code of Conduct also applies outside the project spaces when the Project +Steward has a reasonable belief that an individual's behavior may have a +negative impact on the project or its community. + +## Conflict Resolution + +We do not believe that all conflict is bad; healthy debate and disagreement +often yield positive results. However, it is never okay to be disrespectful or +to engage in behavior that violates the project’s code of conduct. + +If you see someone violating the code of conduct, you are encouraged to address +the behavior directly with those involved. Many issues can be resolved quickly +and easily, and this gives people more control over the outcome of their +dispute. If you are unable to resolve the matter for any reason, or if the +behavior is threatening or harassing, report it. We are dedicated to providing +an environment where participants feel welcome and safe. + +Reports should be directed to *[PROJECT STEWARD NAME(s) AND EMAIL(s)]*, the +Project Steward(s) for *[PROJECT NAME]*. It is the Project Steward’s duty to +receive and address reported violations of the code of conduct. They will then +work with a committee consisting of representatives from the Open Source +Programs Office and the Google Open Source Strategy team. If for any reason you +are uncomfortable reaching out to the Project Steward, please email +opensource@google.com. + +We will investigate every complaint, but you may not receive a direct response. +We will use our discretion in determining when and how to follow up on reported +incidents, which may range from not taking action to permanent expulsion from +the project and project-sponsored spaces. We will notify the accused of the +report and provide them an opportunity to discuss it before any action is taken. +The identity of the reporter will be omitted from the details of the report +supplied to the accused. In potentially harmful situations, such as ongoing +harassment or threats to anyone's safety, we may take action without notice. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 1.4, +available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct/ diff --git a/demos/agent-secret/README.md b/demos/agent-secret/README.md new file mode 100644 index 000000000..23c0f897d --- /dev/null +++ b/demos/agent-secret/README.md @@ -0,0 +1,78 @@ +# Secret Agent Demo: Self-Suspension & Persistent Identity + +This demo showcases a "Zero-Idle" agentic lifecycle using a specialized Go server. It demonstrates how Agent Substrate treats process state as a portable asset, enabling both **Self-Suspension** and **Persistent Working Memory** (via a RAM-based secret). + +## Key Concepts Demonstrated +* **Self-Suspension:** The agent process calls the Substrate Control Plane API (`SuspendActor`) automatically after responding to a request, yielding compute resources as soon as it becomes idle. +* **Persistent Working Memory:** The agent generates a random secret in its volatile RAM on process start. Substrate preserves this exact memory state across physical resumptions, proving it doesn't just "restart" containers but actually rehydrates living processes. +* **High-Density Multiplexing:** Demonstrates how dozens of isolated, stateful sessions can coexist on a small pool of physical hardware. + +--- + +## 🛠️ Step-by-Step Setup + +### 1. Prerequisites +* A GKE cluster with **Agent Substrate** installed. +* `ko` installed (for building and deploying Go images). +* `kubectl-ate` CLI built in the root directory. + +### 2. Deploy the Infrastructure +Use the core installation script to build the image and apply the manifests: +```bash +./hack/install-ate.sh --deploy-demo-agent-secret +``` + +### 3. Scale the Worker Pool +To demonstrate oversubscription and density, we recommend scaling the physical pool to 8 workers: +```bash +kubectl patch workerpool agent-secret -n ate-demo-secret-agent-v2 \ + --type='merge' -p '{"spec":{"replicas":8}}' +``` + +--- + +## 📽️ Interaction Guide + +### 1. Basic Interaction +Create a single actor and watch it automatically yield compute after use: +```bash +# Create the actor +./kubectl-ate create actor my-agent --template ate-demo-secret-agent-v2/agent-secret + +# Send a request via the Substrate Router (Note the official DNS suffix) +curl -H "Host: my-agent.actors.resources.substrate.k8s.io" http://localhost:8000 +``` + +**What to observe:** +* In a separate terminal, run `watch ./kubectl-ate get actors`. +* Notice that the actor status flips to `STATUS_RUNNING` instantly upon the request, and then **automatically** flips back to `STATUS_SUSPENDED` after the 7-second "visibility linger" period. + +### 2. Verify Identity Persistence +Send another request to the same actor: +```bash +curl -H "Host: my-agent.actors.resources.substrate.k8s.io" http://localhost:8000 +``` +The "Identity" secret returned will be identical to the first response, even if the actor was resumed on a different physical pod. This proves the volatile RAM survived the hibernation cycle. + +### 3. Demonstrating Massive Density (The "Wave" Swarm) +To show the scale at which Substrate can manage sessions, run this loop to populate the registry with 23 additional stateful sessions: + +```bash +for i in {001..023}; do + ./kubectl-ate create actor session-$i --template ate-demo-secret-agent-v2/agent-secret +done +``` + +Now, trigger a "Wave Pulse" to show multiplexing in action. This command sends requests in groups of 8, allowing you to see the physical grid fill and clear in a rhythmic "conveyor belt" fashion: + +```bash +# Pulse in 3 waves of 8 +for wave in 0 1 2; do + echo "Triggering Wave $((wave + 1))..." + for i in {1..8}; do + num=$(printf "%03d" $((wave * 8 + i))) + curl -s -H "Host: session-$num.actors.resources.substrate.k8s.io" http://localhost:8000 & + done + sleep 8 # 7s linger + 1s buffer +done +``` diff --git a/demos/agent-secret/main.go b/demos/agent-secret/main.go new file mode 100644 index 000000000..44670b47c --- /dev/null +++ b/demos/agent-secret/main.go @@ -0,0 +1,138 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "log" + "net/http" + "os" + "strings" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +var residentSecret string + +func init() { + // Unique ID generated in volatile RAM on process start + residentSecret = fmt.Sprintf("SECRET-%d", time.Now().UnixNano()%10000) +} + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte("OK")) + }) + mux.HandleFunc("/", handleRequest) + + port := os.Getenv("PORT") + if port == "" { + port = "80" + } + + log.Printf("Self-Suspending Agent listening on :%s with Identity: %s", port, residentSecret) + if err := http.ListenAndServe(":"+port, mux); err != nil { + log.Fatalf("failed to serve: %v", err) + } +} + +func handleRequest(w http.ResponseWriter, r *http.Request) { + log.Printf("DEBUG: Request received. Path=%s Host=%s", r.URL.Path, r.Host) + + // 1. Identify Actor (Robust extraction) + // New architecture uses Host: .actors.resources.substrate.k8s.io + actorID := r.Header.Get("X-AgentSet-Session") + if actorID == "" { + actorID = r.Header.Get("x-agentset-session") + } + if actorID == "" { + host := r.Host + if host == "" { + host = r.Header.Get("Host") + } + // Extract prefix from .actors.resources.substrate.k8s.io + parts := strings.Split(host, ".") + if len(parts) > 1 { + actorID = parts[0] + } + } + + if actorID == "" { + actorID = "unknown" + } + + log.Printf("DEBUG: Identified ActorID: [%s]", actorID) + + body, _ := io.ReadAll(r.Body) + message := string(body) + if message == "" { + message = "Status Check" + } + + // 1. Respond to user + var sb strings.Builder + sb.WriteString(fmt.Sprintf("Agent Response: [%s] | Identity: %s | Session: %s\n", message, residentSecret, actorID)) + if actorID == "" { + sb.WriteString("DEBUG: ID Missing. Headers received:\n") + for k, v := range r.Header { + sb.WriteString(fmt.Sprintf(" %s: %v\n", k, v)) + } + } + response := sb.String() + w.Header().Set("Content-Type", "text/plain") + w.WriteHeader(http.StatusOK) + w.Write([]byte(response)) + + // 2. Self-Suspend (Zero-Idle) + if actorID != "" && actorID != "localhost" && !strings.Contains(actorID, ":") { + // Use a goroutine to avoid blocking the HTTP response + go func() { + // We linger for 7 seconds in this demo to make the multiplexing visible in the CLI. + time.Sleep(7 * time.Second) + suspendSelf(actorID) + }() + } +} + +func suspendSelf(id string) { + apiAddr := os.Getenv("ATE_API_ADDR") + if apiAddr == "" { + apiAddr = "api.ate-system.svc.cluster.local:443" + } + + creds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) + conn, err := grpc.Dial(apiAddr, grpc.WithTransportCredentials(creds)) + if err != nil { + log.Printf("Failed to connect to ATE API: %v", err) + return + } + defer conn.Close() + + client := ateapipb.NewControlClient(conn) + + log.Printf("Yielding compute. Requesting self-suspension for actor %s...", id) + _, err = client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ActorId: id}) + if err != nil { + log.Printf("Failed to self-suspend: %v", err) + } +} diff --git a/demos/claude-code-multiplex/README.md b/demos/claude-code-multiplex/README.md new file mode 100644 index 000000000..183a716b1 --- /dev/null +++ b/demos/claude-code-multiplex/README.md @@ -0,0 +1,128 @@ +# Claude Code Multiplex Demo + +A demo of three Claude-Code-driven agents sharing two Agent Substrate pods. Substrate suspends idle agents and resumes them on demand, so the cluster runs *fewer pods than agents*. + +**Walkthrough video (150s):** https://storage.googleapis.com/yojowa-claw-demo-screenshots/multiplex-demo-2026-05-18-captions.webm + +The video shows the three-agent rotation end-to-end: queued → running → completed, with the third agent suspending while the other two run, and substrate cycling pod ownership as tasks complete. + +> [!NOTE] +> This demo intentionally provisions **two pods for three agents** to exercise substrate's suspend/resume path. The same pattern scales — ten agents on three pods, a hundred agents on twenty. + +## What this shows + +- Three Claude Code agents (`luna`, `mars`, `orion`) registered as Substrate actors. +- A `WorkerPool` of two pods. +- A small web UI that drives "give a task" against random idle agents and renders the queued/running/completed badge state per agent. +- Substrate handles the hard parts: state snapshot on suspend, scheduling decisions, resume-correctness when a pod becomes available. + +## Audience + +This guide assumes you know Kubernetes and the general shape of agent runtimes (autonomy + LLM API access). It does **not** assume prior Substrate experience. + +## Prerequisites + +- A Kubernetes cluster with **Agent Substrate** installed (`./hack/install-ate.sh` from this repo's root). +- `kubectl` configured against that cluster (the dashboard uses the operator's kubeconfig via [`client-go`](https://github.com/kubernetes/client-go) for pod-log reads). +- Network reach to the substrate **ateapi** gRPC service (`ateapi.ate-system:8080`). When running the dashboard from outside the cluster, port-forward it in a separate terminal (same convention as [`demos/sandbox/README.md`](../sandbox/README.md#3-port-forward-services)) and keep it running for the lifetime of the demo: + ```bash + # Terminal 1: ateapi port-forward + kubectl port-forward svc/ateapi 8080:8080 -n ate-system + ``` +- An **Anthropic API key** (the agents call Claude). +- A GCS bucket for substrate state snapshots (configured during Substrate install). +- `KO_DOCKER_REPO` set to a registry you can push to (e.g. `gcr.io/${PROJECT_ID}/ate-images`, same as `hack/ate-dev-env.sh.example`). The deploy step builds and pushes the workload image there with a sha256-pinned reference. +- `docker buildx` (the deploy function builds the workload image — a Dockerfile-based Python + Claude Code wrapper, not a Go binary, so `ko` doesn't apply for the workload itself). + +## Components + +| Path | Purpose | +|---|---| +| `manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl` | Namespace, WorkerPool, ActorTemplates in a single envsubst template | +| `hack/install-demo-claude-code-multiplex.sh` | Sourced by `install-ate.sh`; registers `--deploy-demo-claude-code-multiplex` and `--delete-demo-claude-code-multiplex` | +| `demos/claude-code-multiplex/workload/` | The agent container image source (Dockerfile + entrypoint that wires Claude Code; built and pushed by the deploy step) | +| `demos/claude-code-multiplex/ui/` | Static dashboard (`index.html` + `server.go`) that talks to the cluster | + +(Files will be added across iterations of this PR.) + +## How to Run + +### 1. Deploy the demo + +From the repo root, with your Anthropic key and substrate bucket name in the environment: + +```bash +ANTHROPIC_API_KEY=sk-ant-... \ +BUCKET_NAME=your-substrate-bucket \ + ./hack/install-ate.sh --deploy-demo-claude-code-multiplex +``` + +This creates the `claude-multiplex-demo` namespace, a 2-pod `WorkerPool`, and three `ActorTemplate` objects named `luna`, `mars`, `orion`. Under the hood, the deploy function builds the workload image with `docker buildx`, pushes it to `${KO_DOCKER_REPO}/claude-multiplex-demo-workload`, resolves the pushed sha256 digest, and substitutes the digest-pinned reference plus `ANTHROPIC_API_KEY` and `BUCKET_NAME` into the manifest template at apply time. + +### 2. Start the dashboard + +The dashboard is a small Go HTTP server that reads worker and actor state from the substrate **ateapi** gRPC service (mirroring the pattern in `demos/sandbox/client/main.go`) and pod logs from the Kubernetes API via [`client-go`](https://github.com/kubernetes/client-go). No `kubectl` process invocations. + +Make sure the ateapi port-forward from the [Prerequisites](#prerequisites) is still running, then: + +```bash +cd demos/claude-code-multiplex/ui +PORT=8090 ATEAPI_ADDR=localhost:8080 go run . +``` + +Or build a binary: + +```bash +cd demos/claude-code-multiplex/ui +go build -o ui-server . +PORT=8090 ATEAPI_ADDR=localhost:8080 ./ui-server +``` + +Either way, the UI is served on `http://localhost:8090` (or whatever `PORT` you pick — pick something that doesn't collide with the ateapi port-forward). + +Env vars: + +| Var | Default | Purpose | +|---|---|---| +| `PORT` | `8080` | TCP port the dashboard binds (pick `≠ ATEAPI_ADDR`'s port when both run on the same host). | +| `ATEAPI_ADDR` | `localhost:8080` | Address of the substrate ateapi gRPC service. | +| `DEMO_NAMESPACE` | `claude-multiplex-demo` | Kubernetes namespace the dashboard filters to and reads pod logs from. | + +`GET /healthz` reports whether the kube client picked up a cluster context (`logs:true|false`) — useful for quick smoke-tests after starting the server. + +### 3. Drive the demo + +Click "Give a task". The UI picks a random idle agent and creates a task for it. Watch: + +- Badge flips to `queued` (the agent has work but isn't bound to a pod yet). +- Substrate finds a free pod and binds the agent. Badge flips to `running`. +- The agent calls Claude, writes a result, exits. Badge flips to `completed`. +- Substrate notices the inactivity and suspends the agent after a short idle window. +- The released pod becomes available for the next queued task on a different agent. + +With three agents and two pods, the third agent stays suspended (state snapshotted) until a pod opens up. + +## Upstream blockers worked around for this demo + +This demo currently applies workarounds at runtime for three Substrate issues. Each will be addressed by a separate upstream fix PR; details + workarounds in the linked issue threads. + +- **`#189`** — Atelet OCI bundle gaps (`Args`, `Secret`, symlinks). Bundled fix PR forthcoming. +- **`#197` Bug 2a** — `valueFrom.secretKeyRef` on `ActorTemplate` container env is not supported today. `ANTHROPIC_API_KEY` is passed as a plain `value:` env var (envsubst-substituted at apply time) until upstream support lands. +- **`#197` Bug 3** — Atelet symlink resolution. Fix PR forthcoming. + +> [!NOTE] +> `@AlexBulankou` asked for this guide as the main deliverable for the Claude-Code-on-Substrate demo work. The fix PRs are filed separately so each blocker has its own upstream review thread. + +## Status + +**This PR is a draft.** Initial commit lands the structural README. Subsequent commits will add the manifests, the workload Dockerfile/entrypoint, and the UI source. Each addition will keep the README in sync. + +Feedback on shape/audience welcome before content fills out. + +## Teardown + +```bash +./hack/install-ate.sh --delete-demo-claude-code-multiplex +``` + +This removes the `claude-multiplex-demo` namespace and all the resources created by the deploy step. You can also stop the port-forward and the dashboard processes in their respective terminals. diff --git a/demos/claude-code-multiplex/ui/index.html b/demos/claude-code-multiplex/ui/index.html new file mode 100644 index 000000000..a1eb67a4a --- /dev/null +++ b/demos/claude-code-multiplex/ui/index.html @@ -0,0 +1,424 @@ + + + + + + +Claude multiplex demo + + + +
+

Claude multiplex demo

+
connecting…
+
+ +

+ This demo runs 3 Claude Code agents on + 2 substrate worker pods. Each agent has its own short prompt + and works in a loop: ask Claude, print the answer, idle for 45 seconds, + repeat. While an agent is idle, substrate can suspend it + (snapshot its process state, free its pod) and let a different agent borrow + that pod — that’s the multiplex. The dashboard + refreshes every 2.5 seconds; pods, actors, and logs are all live so you + can watch the rotation happen. +

+ +
+ Approximate cost while running + GCP infrastructure: ~$0.40/hr + Claude Code (3 agents): ~$5/hr when active + Total: ~$5.40/hr typical + + GCP figure is one n2-standard-8 VM in us-central1 (ephemeral IP free). Claude Code figure + assumes Sonnet 4.x at published rates, each agent firing one short prompt every 45 s, + multiplexed across 2 pods (so about 2 of the 3 agents are actively running at any moment). + During the current substrate boundary the agents aren’t invoking Claude, so the real + spend is just the VM — that flips up once the substrate chain resolves. + +
+ +
+
+

Tasks

+ + +
+

+ Click Give a task to assign a randomly chosen short task to a + randomly chosen agent. Each task moves through three states — + queued + while the agent is suspended, + running + while it owns a worker pod, and + completed + once substrate suspends it again. +

+
+
no tasks yet — click Give a task to start
+
+
+ +
+
+

Worker pods

+

+ The pool of substrate-managed pods that actually host running agents. The + WorkerPool is configured with 2 replicas for + 3 agents, so substrate is forced to share — at any + moment at most 2 agents own pods, and the third is suspended waiting its + turn. Substrate rotates ownership as agents transition between active and + idle phases. +

+
loading…
+
+
+

Actors & templates

+

+ ActorTemplates define each agent (container image, + prompt, idle interval). Actors are the live instances + bound — or not — to a worker pod. Watch the + phase: Running means the actor is on a pod + executing right now; Suspended means its state is stored and + it’s waiting for a free pod; Resuming / + ResumeGoldenActor are the substrate transitions in between. +

+
loading…
+
+
+ +

Live logs (per pod, last 25 lines, all containers)

+

+ Each card below tails the logs of one worker pod. Because substrate moves + agents between pods, the log stream you see in a single card switches + ownership over time — you’ll see one agent’s + [demo-actor: agent-luna] tick output, then a transition, then + [demo-actor: agent-mars] picking up on the same pod. That + ownership transition is the multiplex in action. +

+
+ + + + diff --git a/demos/claude-code-multiplex/ui/server.go b/demos/claude-code-multiplex/ui/server.go new file mode 100644 index 000000000..7624f9c2d --- /dev/null +++ b/demos/claude-code-multiplex/ui/server.go @@ -0,0 +1,542 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Demo UI server — substrate multiplex visualization. +// +// Tiny stdlib HTTP server. Reads worker + actor state from the substrate +// ateapi gRPC service, reads pod logs from the k8s API via client-go, +// exposes JSON endpoints, and serves index.html that polls them. +// +// No kubectl shellouts — all data flows go through: +// 1. ateapi gRPC (workers / actors / actor names) — mirrors the pattern +// in demos/sandbox/client/main.go. +// 2. client-go corev1 typed client (pod logs) — uses the operator's +// kubeconfig when running outside the cluster; in-cluster service +// account credentials otherwise. +// +// Prereq when running outside the cluster: +// +// kubectl port-forward svc/ateapi 8080:8080 -n ate-system & +// PORT=8090 ATEAPI_ADDR=localhost:8080 DEMO_NAMESPACE=claude-multiplex-demo go run ./server.go +// +// (Pick a UI PORT that doesn't collide with the port-forward.) +package main + +import ( + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "log" + "math/rand" + "net/http" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "time" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +const ( + defaultPort = "8080" + defaultNamespace = "claude-multiplex-demo" + defaultAteapiAddr = "localhost:8080" + maxAssignments = 50 + rpcTimeout = 10 * time.Second + logTailLines = int64(25) + + // Assignment lifecycle states the UI badge logic reads. + // queued → running → completed; computeState drives the + // transitions from elapsed-since-creation. + stateQueued = "queued" + stateRunning = "running" + stateCompleted = "completed" +) + +var predefinedTasks = []string{ + "Review main.py and suggest two improvements", + "Explain how a Kubernetes ReplicaSet differs from a Deployment", + "Write a Python function to detect duplicate items in a list", + "Summarize the difference between a Pod and a Job in Kubernetes", + "List three best practices for writing testable Python code", + "Draft a one-paragraph summary of Python garbage collection", + "Suggest two ways to make a Kubernetes Service more resilient", + "Write a unit test for a function that returns the max of two integers", + "Explain the role of an admission controller in Kubernetes", + "Outline a backoff strategy for a flaky HTTP client", +} + +type assignment struct { + ID string `json:"id"` + Agent string `json:"agent"` + Task string `json:"task"` + State string `json:"state"` + CreatedAt float64 `json:"created_at"` + StartedAt *float64 `json:"started_at"` + CompletedAt *float64 `json:"completed_at"` + QueueFor float64 `json:"queue_for"` + RunFor float64 `json:"run_for"` +} + +// podSummary is the per-worker shape the UI's index.html renders. Field +// names match the original kubectl-shellout JSON contract so the page +// doesn't need to change. Some k8s-specific fields (Node, StartedAt, +// Image) aren't surfaced by ateapi today; we backfill with substrate- +// native semantics: Node ← worker_pool, StartedAt ← "" (omit), and the +// Image field is dropped since the UI doesn't read it. +type podSummary struct { + Name string `json:"name"` + Node string `json:"node"` + Phase string `json:"phase"` + Ready bool `json:"ready"` + StartedAt string `json:"started_at"` +} + +// actorSummary mirrors the original kubectl-plugin JSON contract. Kind +// is always "Actor" now (ActorTemplates / WorkerPools are not surfaced +// via ateapi today); Phase is derived from the proto Status enum. +type actorSummary struct { + Kind string `json:"kind"` + Name string `json:"name"` + Phase string `json:"phase"` + Message string `json:"message"` +} + +var ( + namespace = envOr("DEMO_NAMESPACE", defaultNamespace) + ateapiAddr = envOr("ATEAPI_ADDR", defaultAteapiAddr) + rootDir = mustRootDir() + mu sync.Mutex + assignments = make([]*assignment, 0, maxAssignments) // newest first + + ateClient ateapipb.ControlClient + ateConn *grpc.ClientConn + kubeClient *kubernetes.Clientset +) + +func envOr(key, fallback string) string { + if v := os.Getenv(key); v != "" { + return v + } + return fallback +} + +// mustRootDir returns the directory holding this server's index.html. +// Use os.Executable when available (covers `go build` + run); fall +// back to the current working directory (covers `go run` where the +// executable is in /tmp). +func mustRootDir() string { + if exe, err := os.Executable(); err == nil { + if d := filepath.Dir(exe); fileExists(filepath.Join(d, "index.html")) { + return d + } + } + if wd, err := os.Getwd(); err == nil { + return wd + } + return "." +} + +func fileExists(p string) bool { + _, err := os.Stat(p) + return err == nil +} + +// dialAteAPI opens a gRPC client to the substrate ateapi service. +// Mirrors demos/sandbox/client/main.go: TLS with InsecureSkipVerify +// (ateapi serves a self-signed cert; the demo trusts whichever +// instance the port-forward / in-cluster DNS resolves to). +func dialAteAPI(endpoint string) (ateapipb.ControlClient, *grpc.ClientConn, error) { + creds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) + conn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(creds)) + if err != nil { + return nil, nil, err + } + return ateapipb.NewControlClient(conn), conn, nil +} + +// newKubeClient returns a typed kubernetes client. Tries in-cluster +// config first (works when running as a pod); falls back to the +// operator's kubeconfig (works when running on a dev VM after +// `gcloud container clusters get-credentials` / `kind export +// kubeconfig`). Returns nil + nil error when neither is available +// — log endpoints will then 503 gracefully without crashing the +// server (handy when iterating on the demo locally with no +// cluster context). +func newKubeClient() (*kubernetes.Clientset, error) { + if cfg, err := rest.InClusterConfig(); err == nil { + return kubernetes.NewForConfig(cfg) + } + + loader := clientcmd.NewDefaultClientConfigLoadingRules() + cfg, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + loader, &clientcmd.ConfigOverrides{}).ClientConfig() + if err != nil { + // No usable kube config — return nil clientset, no error; + // handleLogs will degrade to a clear 503. + log.Printf("[ui] no kube context available (logs disabled): %v", err) + return nil, nil + } + return kubernetes.NewForConfig(cfg) +} + +// actorStatusString maps the proto Status enum to the human-readable +// phase string the UI's badge logic understands (running / suspended +// / etc). +func actorStatusString(s ateapipb.Actor_Status) string { + switch s { + case ateapipb.Actor_STATUS_RESUMING: + return "Resuming" + case ateapipb.Actor_STATUS_RUNNING: + return "Running" + case ateapipb.Actor_STATUS_SUSPENDING: + return "Suspending" + case ateapipb.Actor_STATUS_SUSPENDED: + return "Suspended" + default: + return "?" + } +} + +// workerPhase derives a pod-like phase string from a substrate Worker. +// A worker hosting an actor is "Running"; an idle worker is "Idle". +// The UI's badgeFor() treats "running" as green; "idle" falls through +// to the neutral badge, which is the right visual treatment. +func workerPhase(w *ateapipb.Worker) string { + if w.GetActorId() != "" { + return "Running" + } + return "Idle" +} + +// listActorNames returns current actor IDs in the namespace via +// ateapi. Replaces the prior kubectl-shellout fallback chain. +func listActorNames(ctx context.Context) []string { + if ateClient == nil { + return nil + } + rctx, cancel := context.WithTimeout(ctx, rpcTimeout) + defer cancel() + resp, err := ateClient.ListActors(rctx, &ateapipb.ListActorsRequest{}) + if err != nil { + log.Printf("[ui] ListActors error: %v", err) + return nil + } + names := make([]string, 0, len(resp.GetActors())) + for _, a := range resp.GetActors() { + if id := a.GetActorId(); id != "" { + names = append(names, id) + } + } + sort.Strings(names) + return names +} + +// computeState returns the timer-driven UI state for an assignment. +// queued → running → completed (purely client-time-driven; the +// substrate side has no concept of these per-task states). +func computeState(asg *assignment) string { + elapsed := nowSec() - asg.CreatedAt + if elapsed < asg.QueueFor { + return stateQueued + } + if elapsed < asg.QueueFor+asg.RunFor { + return stateRunning + } + return stateCompleted +} + +// applyComputedStates walks current assignments and stamps started_at / +// completed_at as states advance. Caller must NOT hold mu. +func applyComputedStates() { + mu.Lock() + defer mu.Unlock() + for _, asg := range assignments { + newState := computeState(asg) + if newState == asg.State { + continue + } + asg.State = newState + if newState == stateRunning && asg.StartedAt == nil { + v := asg.CreatedAt + asg.QueueFor + asg.StartedAt = &v + } else if newState == stateCompleted && asg.CompletedAt == nil { + v := asg.CreatedAt + asg.QueueFor + asg.RunFor + asg.CompletedAt = &v + } + } +} + +func nowSec() float64 { + return float64(time.Now().UnixNano()) / 1e9 +} + +// giveTask picks a random task + random agent and records the assignment. +// Returns nil-string error if no agents. +func giveTask(ctx context.Context) (*assignment, string) { + agents := listActorNames(ctx) + if len(agents) == 0 { + return nil, "no agents available in namespace" + } + now := nowSec() + asg := &assignment{ + ID: fmt.Sprintf("asg-%d", time.Now().UnixMilli()), + Agent: agents[rand.Intn(len(agents))], + Task: predefinedTasks[rand.Intn(len(predefinedTasks))], + State: stateQueued, + CreatedAt: now, + QueueFor: roundOne(2.0 + rand.Float64()*3.0), // 2.0–5.0 + RunFor: roundOne(9.0 + rand.Float64()*7.0), // 9.0–16.0 + } + mu.Lock() + defer mu.Unlock() + assignments = append([]*assignment{asg}, assignments...) + if len(assignments) > maxAssignments { + assignments = assignments[:maxAssignments] + } + return asg, "" +} + +func roundOne(v float64) float64 { + return float64(int(v*10+0.5)) / 10 +} + +// writeJSON serializes body as JSON with no-store cache headers. +func writeJSON(w http.ResponseWriter, status int, body interface{}) { + data, err := json.Marshal(body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Cache-Control", "no-store") + w.WriteHeader(status) + _, _ = w.Write(data) +} + +func handleIndex(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" && r.URL.Path != "/index.html" { + http.NotFound(w, r) + return + } + f, err := os.Open(filepath.Join(rootDir, "index.html")) + if err != nil { + http.NotFound(w, r) + return + } + defer f.Close() + w.Header().Set("Content-Type", "text/html; charset=utf-8") + _, _ = io.Copy(w, f) +} + +func handleHealthz(w http.ResponseWriter, _ *http.Request) { + writeJSON(w, http.StatusOK, map[string]interface{}{ + "ok": true, + "namespace": namespace, + "ateapi_addr": ateapiAddr, + "logs": kubeClient != nil, + }) +} + +// handlePods returns worker-shaped JSON sourced from ateapi.ListWorkers. +// The JSON shape mirrors the original kubectl-shellout contract so +// index.html doesn't need to change. +func handlePods(w http.ResponseWriter, r *http.Request) { + if ateClient == nil { + writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "ateapi client not initialized"}) + return + } + ctx, cancel := context.WithTimeout(r.Context(), rpcTimeout) + defer cancel() + resp, err := ateClient.ListWorkers(ctx, &ateapipb.ListWorkersRequest{}) + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "ListWorkers: " + err.Error()}) + return + } + pods := make([]podSummary, 0, len(resp.GetWorkers())) + for _, wk := range resp.GetWorkers() { + // Filter to the demo namespace when set — workers may live + // in their own pool namespace (worker_namespace) so we + // compare against actor_namespace too. + if namespace != "" && wk.GetActorNamespace() != "" && wk.GetActorNamespace() != namespace { + continue + } + pods = append(pods, podSummary{ + Name: wk.GetWorkerPod(), + Node: wk.GetWorkerPool(), // closest semantic analog + Phase: workerPhase(wk), + Ready: wk.GetActorId() != "", + StartedAt: "", // not exposed by ateapi today + }) + } + sort.Slice(pods, func(i, j int) bool { return pods[i].Name < pods[j].Name }) + writeJSON(w, http.StatusOK, map[string][]podSummary{"pods": pods}) +} + +// handleActors returns actor-shaped JSON sourced from ateapi.ListActors. +// ActorTemplates / WorkerPools (k8s CRDs) are no longer surfaced — +// substrate-native Actors are the canonical demo entity. +func handleActors(w http.ResponseWriter, r *http.Request) { + if ateClient == nil { + writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "ateapi client not initialized"}) + return + } + ctx, cancel := context.WithTimeout(r.Context(), rpcTimeout) + defer cancel() + resp, err := ateClient.ListActors(ctx, &ateapipb.ListActorsRequest{}) + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "ListActors: " + err.Error()}) + return + } + actors := make([]actorSummary, 0, len(resp.GetActors())) + for _, a := range resp.GetActors() { + if namespace != "" && a.GetActorTemplateNamespace() != "" && a.GetActorTemplateNamespace() != namespace { + continue + } + // Carry the template name as the meta message so the UI's + // secondary line shows useful provenance (the original + // kubectl path put k8s `status.message` here — for + // substrate Actors there's no equivalent, so the template + // name is the closest semantic match). + msg := "" + if t := a.GetActorTemplateName(); t != "" { + msg = "template: " + t + } + actors = append(actors, actorSummary{ + Kind: "Actor", + Name: a.GetActorId(), + Phase: actorStatusString(a.GetStatus()), + Message: msg, + }) + } + sort.Slice(actors, func(i, j int) bool { return actors[i].Name < actors[j].Name }) + writeJSON(w, http.StatusOK, map[string][]actorSummary{"actors": actors}) +} + +// handleLogs streams the last N lines of a pod's logs via the typed +// k8s client. Replaces the prior `kubectl logs --tail=25` shellout. +func handleLogs(w http.ResponseWriter, r *http.Request) { + pod := strings.TrimPrefix(r.URL.Path, "/api/logs/") + pod = strings.Trim(pod, "/") + if pod == "" || strings.Contains(pod, "/") { + writeJSON(w, http.StatusBadRequest, map[string]string{"error": "bad pod ref"}) + return + } + if kubeClient == nil { + writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "k8s client not initialized"}) + return + } + ctx, cancel := context.WithTimeout(r.Context(), rpcTimeout) + defer cancel() + tail := logTailLines + opts := &corev1.PodLogOptions{TailLines: &tail} + req := kubeClient.CoreV1().Pods(namespace).GetLogs(pod, opts) + stream, err := req.Stream(ctx) + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + defer stream.Close() + data, err := io.ReadAll(stream) + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error(), "logs": string(data)}) + return + } + writeJSON(w, http.StatusOK, map[string]string{"logs": string(data), "stderr": ""}) +} + +func handleTaskStatus(w http.ResponseWriter, _ *http.Request) { + applyComputedStates() + mu.Lock() + snapshot := make([]*assignment, len(assignments)) + copy(snapshot, assignments) + mu.Unlock() + writeJSON(w, http.StatusOK, map[string][]*assignment{"assignments": snapshot}) +} + +func handleGiveTask(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.NotFound(w, r) + return + } + // Drain request body if any (we don't actually need it; click semantics only). + _, _ = io.Copy(io.Discard, r.Body) + _ = r.Body.Close() + + asg, errMsg := giveTask(r.Context()) + if errMsg != "" { + writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": errMsg}) + return + } + writeJSON(w, http.StatusOK, asg) +} + +func main() { + rand.Seed(time.Now().UnixNano()) + + port := envOr("PORT", defaultPort) + + // Open the ateapi connection up front so the UI surfaces a clear + // startup error if the operator forgot the port-forward, rather + // than per-request failures with cryptic gRPC messages. + log.Printf("[ui] dialing ateapi at %s", ateapiAddr) + cli, conn, err := dialAteAPI(ateapiAddr) + if err != nil { + log.Fatalf("dial ateapi: %v", err) + } + ateClient = cli + ateConn = conn + defer ateConn.Close() + + // Best-effort k8s client for logs; nil is OK (handleLogs degrades + // to a 503 with a clear message). This lets the demo start even + // when no cluster context is configured — useful for quick UI + // shape iteration. + kc, kerr := newKubeClient() + if kerr != nil { + log.Printf("[ui] kube client init error (logs disabled): %v", kerr) + } + kubeClient = kc + + mux := http.NewServeMux() + mux.HandleFunc("/", handleIndex) + mux.HandleFunc("/healthz", handleHealthz) + mux.HandleFunc("/api/pods", handlePods) + mux.HandleFunc("/api/actors", handleActors) + mux.HandleFunc("/api/logs/", handleLogs) + mux.HandleFunc("/api/task-status", handleTaskStatus) + mux.HandleFunc("/api/give-task", handleGiveTask) + + addr := "0.0.0.0:" + port + log.Printf("[ui] serving %s (namespace=%s ateapi=%s logs=%t)", addr, namespace, ateapiAddr, kubeClient != nil) + + srv := &http.Server{ + Addr: addr, + Handler: mux, + ReadHeaderTimeout: 5 * time.Second, + } + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatalf("server error: %v", err) + } +} diff --git a/demos/claude-code-multiplex/workload/Dockerfile b/demos/claude-code-multiplex/workload/Dockerfile new file mode 100644 index 000000000..5b013e548 --- /dev/null +++ b/demos/claude-code-multiplex/workload/Dockerfile @@ -0,0 +1,29 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM node:20-slim + +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates curl \ + && rm -rf /var/lib/apt/lists/* + +RUN npm install -g @anthropic-ai/claude-code@latest + +COPY run.sh /run.sh +RUN chmod +x /run.sh + +ENV TASK="Tell me a fact about the moon." +ENV INTERVAL_SECONDS=60 + +ENTRYPOINT ["/run.sh"] diff --git a/demos/claude-code-multiplex/workload/run.sh b/demos/claude-code-multiplex/workload/run.sh new file mode 100755 index 000000000..b13508661 --- /dev/null +++ b/demos/claude-code-multiplex/workload/run.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Demo workload entrypoint: periodically invokes Claude Code with a task and +# idles between intervals. The idle window is what substrate uses to suspend +# this actor and multiplex its worker onto another actor. +# +# Env vars: +# TASK — the prompt to pass to claude-code each tick +# INTERVAL_SECONDS — sleep length between ticks (longer = more multiplex headroom) +# ANTHROPIC_API_KEY — required; supplied via Secret mount + +set -u + +if [ -z "${ANTHROPIC_API_KEY:-}" ]; then + echo "[demo-actor] ERROR: ANTHROPIC_API_KEY not set; refusing to start" >&2 + exit 1 +fi + +ACTOR_NAME="${ACTOR_NAME:-$(hostname)}" +TICK=0 + +echo "[demo-actor:${ACTOR_NAME}] starting; task=\"${TASK}\" interval=${INTERVAL_SECONDS}s" + +while true; do + TICK=$((TICK + 1)) + echo "" + echo "[demo-actor:${ACTOR_NAME}] === tick ${TICK} at $(date -u +%H:%M:%SZ) ===" + echo "[demo-actor:${ACTOR_NAME}] running: ${TASK}" + echo "---" + # --print runs one prompt and exits; output streams to stdout so kubectl logs + # picks it up live. + claude --print "${TASK}" 2>&1 || echo "[demo-actor:${ACTOR_NAME}] claude exited non-zero" + echo "---" + echo "[demo-actor:${ACTOR_NAME}] tick ${TICK} done; sleeping ${INTERVAL_SECONDS}s" + sleep "${INTERVAL_SECONDS}" +done diff --git a/demos/counter/.gitignore b/demos/counter/.gitignore new file mode 100644 index 000000000..eff9f1ef7 --- /dev/null +++ b/demos/counter/.gitignore @@ -0,0 +1,2 @@ +bin/ +/counter diff --git a/demos/counter/README.md b/demos/counter/README.md new file mode 100644 index 000000000..599a6e81d --- /dev/null +++ b/demos/counter/README.md @@ -0,0 +1,87 @@ +# Counter Demo + +This directory contains a demo of a stateful counter application running on Agent Substrate. + +It deploys a simple Go HTTP server (`counter.go`) that increments a counter on every request and preserves state across suspends and resumes. + +## Prerequisites + +- A k8s cluster with Agent Substrate installed (`./hack/install-ate.sh --deploy-ate-system`). +- `ko` installed for building images. +- A GCS bucket for storing snapshots (configured via `BUCKET_NAME` env var). + +## How to Run on Agent Substrate + +### 1. Build and Deploy + +> [!NOTE] +> Do not manually edit `manifests/counter/counter.yaml.tmpl`. The installation script automatically injects your `${BUCKET_NAME}` environment variable during deployment. + +Use the core installation script to build the image and apply the resolved manifests to your cluster: + +```bash +./hack/install-ate.sh --deploy-demo-counter +``` + +This command will: +- Build the counter server image using `ko`. +- Create the `ate-demo-counter` namespace. +- Create the `WorkerPool` and `ActorTemplate`. + +Wait until the template is ready: +```bash +kubectl wait --for=condition=Ready actortemplate/counter -n ate-demo-counter --timeout=5m +``` + +### 2. Create a Counter Actor + +Use `kubectl ate` to create an instance of the counter actor with a chosen ID (e.g., `my-counter-1`): + +```bash +# Install the CLI as a kubectl plugin if not already installed +go install ./cmd/kubectl-ate + +# Create the actor using the counter template. +kubectl ate create actor my-counter-1 --template ate-demo-counter/counter +``` + +### 3. Port-Forward Services + +To interact with the router locally: + +```bash +# Port-forward the Atenet Router +kubectl port-forward -n ate-system svc/atenet-router 8000:80 +``` + +## How to Use + +When you send an HTTP request through the router, Substrate automatically detects the session, activates (resumes) the actor onto an available worker pod, and proxies the traffic. + +1. Send an HTTP POST request to increment the counter: +```bash +curl -X POST -H "Host: my-counter-1.actors.resources.substrate.ate.dev" http://localhost:8000 +``` + +2. Verify that the actor is now in a `RUNNING` state and assigned to a worker pod: +```bash +kubectl ate get actor my-counter-1 +``` + +3. When finished, you can manually suspend the actor back to snapshot storage: +```bash +kubectl ate suspend actor my-counter-1 +``` + +4. To permanently delete the suspended actor: +```bash +kubectl ate delete actor my-counter-1 +``` + +## How to Uninstall + +To remove the counter demo resources from your cluster, run: + +```bash +./hack/install-ate.sh --delete-demo-counter +``` diff --git a/demos/counter/counter.go b/demos/counter/counter.go new file mode 100644 index 000000000..295965f77 --- /dev/null +++ b/demos/counter/counter.go @@ -0,0 +1,143 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Command counter is a simple server that will be used as a worker pod. It listens on ports 80 +// and returns a greeting with the IP of the pod where it is running. +package main + +import ( + "context" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "flag" + "fmt" + "io" + "log/slog" + "net" + "net/http" + "os" + "sync/atomic" + "time" +) + +var requestCount uint64 + +func main() { + flag.Parse() + ctx := context.Background() + + slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil))) + + defaultMux := http.NewServeMux() + defaultMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + count := atomic.AddUint64(&requestCount, 1) + currentIP := getCurrentIP() + response := fmt.Sprintf("hello from: %s | preserved memory count: %d\n", currentIP, count) + slog.InfoContext(ctx, "Handled request", slog.String("response", response)) + w.WriteHeader(http.StatusOK) + w.Write([]byte(response)) + }) + + go func() { + //time.Sleep(60 * time.Second) + slog.InfoContext(ctx, "Starting server on port 80") + if err := http.ListenAndServe(":80", defaultMux); err != nil { + slog.ErrorContext(ctx, "Error starting server", slog.Any("err", err)) + os.Exit(1) + } + }() + + // Write some random data to a file in the root filesystem, to test + // filesystem checkpoint/restore. + if err := writeRandomFile(); err != nil { + slog.InfoContext(ctx, "Error writing random file", slog.Any("err", err)) + } + + count := 0 + if err := pingGoogle(ctx); err != nil { + slog.ErrorContext(ctx, "Error pinging Google", slog.Any("err", err)) + } + slog.InfoContext(ctx, "Count", slog.Int("count", count), slog.String("fshash", hashRandomFile())) + count++ + + for range time.Tick(10 * time.Second) { + if err := pingGoogle(ctx); err != nil { + slog.ErrorContext(ctx, "Error pinging Google", slog.Any("err", err)) + } + slog.InfoContext(ctx, "Count", slog.Int("count", count), slog.String("fshash", hashRandomFile())) + count++ + } +} + +func writeRandomFile() error { + rf, err := os.Create("/random-content-file") + if err != nil { + return fmt.Errorf("while opening file: %w", err) + } + defer rf.Close() + + _, err = io.CopyN(rf, rand.Reader, 1*1024*1024) + if err != nil { + return fmt.Errorf("while copying rand data: %w", err) + } + + return nil +} + +func hashRandomFile() string { + rfBytes, err := os.ReadFile("/random-content-file") + if err != nil { + panic(err) + } + + hash := sha256.Sum256(rfBytes) + return base64.RawStdEncoding.EncodeToString(hash[:]) +} + +// Test outbound connectivity +func pingGoogle(ctx context.Context) error { + // resp, err := http.Get("https://www.google.com") + // if err != nil { + // return fmt.Errorf("while requesting https://www.google.com: %w", err) + // } + // defer resp.Body.Close() + // bodyBytes, err := io.ReadAll(resp.Body) + // if err != nil { + // return fmt.Errorf("while reading body: %w", err) + // } + + // if resp.StatusCode != 200 { + // return fmt.Errorf("bad response code=%d body=%s", resp.StatusCode, string(bodyBytes)) + // } + + return nil +} + +func getCurrentIP() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + slog.Error("Error getting interface addresses", slog.Any("err", err)) + return "x.x.x.x" + } + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String() + } + } + } + return "y.y.y.y" +} diff --git a/demos/sandbox/.gitignore b/demos/sandbox/.gitignore new file mode 100644 index 000000000..63dc2e0f7 --- /dev/null +++ b/demos/sandbox/.gitignore @@ -0,0 +1,3 @@ +bin/ +/client/client +/sandbox diff --git a/demos/sandbox/README.md b/demos/sandbox/README.md new file mode 100644 index 000000000..706a0eeba --- /dev/null +++ b/demos/sandbox/README.md @@ -0,0 +1,101 @@ +# Sandbox Demo + +This directory contains a demo of a stateful sandbox execution environment running on Agent Substrate. + +It allows you to run arbitrary commands in an sandboxed, isolated container (running Alpine Linux) and preserves the execution state across suspends and resumes. + +> [!WARNING] +> **Security Disclaimer:** This demo is not secured by any authorization checks, and the sandbox actor will execute any client-provided commands with no validation. Do not deploy this configuration in production or expose it to untrusted networks. + +## Components + +1. **Sandbox Server (`main.go`)**: The application that runs inside the Agent Substrate actor. It exposes a simple, stateless `/process` endpoint to execute commands. +2. **Sandbox Client (`client/`)**: A CLI REPL tool that allows you to interact with the sandbox actor interactively. + +## Prerequisites + +- A k8s cluster with Agent Substrate installed. +- `ko` installed for building images. +- A GCS bucket for storing snapshots (configured in `manifests/sandbox/sandbox.yaml`). +- `kubectl-ate` CLI installed (can be installed via `go install ./cmd/kubectl-ate`). + +## How to Run on Agent Substrate + +### 1. Build and Deploy + +> [!NOTE] +> Do not manually edit `manifests/sandbox/sandbox.yaml.tmpl`. The installation script automatically injects your `${BUCKET_NAME}` environment variable during deployment. + +Use the core installation script to build the image and apply the resolved manifests to your cluster: + +```bash +./hack/install-ate.sh --deploy-demo-sandbox +``` + +This command will: +- Build the sandbox server image based on Alpine Linux. +- Create the `ate-demo-sandbox` namespace. +- Create the `WorkerPool` and `ActorTemplate`. + +Wait until the template is ready: +```bash +kubectl wait --for=condition=Ready actortemplate/sandbox-template -n ate-demo-sandbox --timeout=5m +``` + +### 2. Create a Sandbox Actor + +Use `kubectl ate` to create an instance of the sandbox actor with a chosen ID (e.g., `my-sandbox-1`): + +```bash +# Install the CLI as a kubectl plugin if not already installed +go install ./cmd/kubectl-ate + +# Create the actor using the kubectl plugin +kubectl ate create actor my-sandbox-1 --template ate-demo-sandbox/sandbox-template +``` + +### 3. Port-Forward Services + +If running clients locally, port-forward the API and router in separate terminals: + +```bash +# Terminal 1: API Server +kubectl port-forward -n ate-system svc/api 8080:443 + +# Terminal 2: Router +kubectl port-forward -n ate-system svc/atenet-router 8000:80 +``` + +## How to Use the Client + +Build and run the client REPL: + +```bash +go build -o bin/sandbox-client ./demos/sandbox/client + +./bin/sandbox-client --ateapi=localhost:8080 --atenet=localhost:8000 --id=my-sandbox-1 +``` + +Once in the `sandbox>` prompt, you can run commands: + +```bash +sandbox> ls -la +sandbox> pwd +sandbox> echo "Hello" > test.txt +sandbox> cat test.txt +``` + +Type `exit` to leave. This will automatically trigger the suspension of the actor. + +To permanently delete the suspended actor: +```bash +kubectl ate delete actor my-sandbox-1 +``` + +## How to Uninstall + +To remove the sandbox demo resources (namespace, workerpool, and template) from your cluster, run: + +```bash +./hack/install-ate.sh --delete-demo-sandbox +``` diff --git a/demos/sandbox/client/main.go b/demos/sandbox/client/main.go new file mode 100644 index 000000000..ba69d0fd6 --- /dev/null +++ b/demos/sandbox/client/main.go @@ -0,0 +1,201 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package main + +import ( + "bufio" + "bytes" + "context" + "crypto/tls" + "encoding/json" + "flag" + "fmt" + "io" + "log" + "net/http" + "os" + "os/signal" + "strings" + "syscall" + + "github.com/agent-substrate/substrate/proto/ateapipb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +type ProcessRequest struct { + Command []string `json:"command"` + EnvVars map[string]string `json:"envvars,omitempty"` + Cwd string `json:"cwd,omitempty"` + Timeout string `json:"timeout,omitempty"` +} + +type ProcessResponse struct { + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` + Error string `json:"error,omitempty"` +} + +func dialAteAPI(endpoint string) (ateapipb.ControlClient, *grpc.ClientConn, error) { + creds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) + + conn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(creds)) + if err != nil { + return nil, nil, err + } + + return ateapipb.NewControlClient(conn), conn, nil +} + +func main() { + actorID := flag.String("id", "", "ID of the sandbox actor (required)") + ateapiAddr := flag.String("ateapi", "localhost:8080", "Address of the ateapi gRPC server") + atenetAddr := flag.String("atenet", "localhost:8000", "Address of the atenet HTTP router") + flag.Parse() + + if *actorID == "" { + log.Fatal("--id is required") + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Handle interrupt signal + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) + go func() { + <-sigChan + fmt.Println("\nInterrupt received, shutting down...") + cancel() + }() + + // 1. Connect to ateapi and Resume Actor + log.Printf("Connecting to ateapi at %s...", *ateapiAddr) + cli, conn, err := dialAteAPI(*ateapiAddr) + if err != nil { + log.Fatalf("Failed to dial ateapi: %v", err) + } + defer conn.Close() + + log.Printf("Resuming actor %s...", *actorID) + _, err = cli.ResumeActor(ctx, &ateapipb.ResumeActorRequest{ActorId: *actorID}) + if err != nil { + log.Fatalf("Failed to resume actor: %v", err) + } + log.Println("Actor resumed successfully.") + + // Ensure we suspend the actor on exit + defer func() { + log.Printf("Suspending actor %s...", *actorID) + suspendCtx := context.Background() + _, err := cli.SuspendActor(suspendCtx, &ateapipb.SuspendActorRequest{ActorId: *actorID}) + if err != nil { + log.Printf("Failed to suspend actor: %v", err) + } else { + log.Println("Actor suspended successfully.") + } + }() + + // 2. Start Input Loop (REPL) + fmt.Println("Starting Sandbox REPL. Type 'exit' to leave.") + + lines := make(chan string) + scanErrors := make(chan error, 1) + + go func() { + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + lines <- scanner.Text() + } + if err := scanner.Err(); err != nil { + scanErrors <- err + } + close(lines) + }() + + for { + fmt.Print("sandbox> ") + select { + case <-ctx.Done(): + // Context was canceled (e.g., CTRL+C) + return + case err := <-scanErrors: + log.Printf("Error reading standard input: %v", err) + return + case line, ok := <-lines: + if !ok { + // Stdin closed (EOF) + return + } + line = strings.TrimSpace(line) + if line == "" { + continue + } + if line == "exit" { + return + } + + // Send command to atenet router + output, err := runCommand(ctx, *atenetAddr, *actorID, line) + if err != nil { + fmt.Printf("Error: %v\n", err) + continue + } + + if output.Error != "" { + fmt.Printf("Command error: %s\n", output.Error) + } + if output.Stdout != "" { + fmt.Print(output.Stdout) + } + if output.Stderr != "" { + fmt.Print(output.Stderr) + } + } + } +} + +func runCommand(ctx context.Context, atenetAddr, actorID, command string) (*ProcessResponse, error) { + url := fmt.Sprintf("http://%s/process", atenetAddr) + + reqBody := ProcessRequest{ + Command: []string{"sh", "-c", command}, + } + jsonBody, _ := json.Marshal(reqBody) + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonBody)) + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + req.Header.Set("Content-Type", "application/json") + req.Host = fmt.Sprintf("%s.actors.resources.substrate.ate.dev", actorID) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(resp.Body) + return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(body)) + } + + var processResp ProcessResponse + if err := json.NewDecoder(resp.Body).Decode(&processResp); err != nil { + return nil, fmt.Errorf("failed to decode response: %w", err) + } + + return &processResp, nil +} diff --git a/demos/sandbox/main.go b/demos/sandbox/main.go new file mode 100644 index 000000000..aca3fed75 --- /dev/null +++ b/demos/sandbox/main.go @@ -0,0 +1,118 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "net/http" + "os" + "os/exec" + "strings" + "time" +) + +type ProcessRequest struct { + Command []string `json:"command"` + EnvVars map[string]string `json:"envvars,omitempty"` + Cwd string `json:"cwd,omitempty"` + Timeout string `json:"timeout,omitempty"` +} + +type ProcessResponse struct { + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` + ExitCode int `json:"exitCode"` + Error string `json:"error,omitempty"` +} + +func main() { + + pattern := "/process" + http.HandleFunc("POST "+pattern, handleProcess) + + port := os.Getenv("PORT") + if port == "" { + port = "80" + } + + log.Printf("Stateless Sandbox serving at port %s, path: %s", port, pattern) + log.Fatal(http.ListenAndServe(":"+port, nil)) +} + +func handleProcess(w http.ResponseWriter, r *http.Request) { + var req ProcessRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Bad request", http.StatusBadRequest) + return + } + + if len(req.Command) == 0 { + http.Error(w, "Command required", http.StatusBadRequest) + return + } + + ctx := r.Context() + if req.Timeout != "" { + duration, err := time.ParseDuration(req.Timeout) + if err != nil { + http.Error(w, fmt.Sprintf("Invalid timeout: %v", err), http.StatusBadRequest) + return + } + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, duration) + defer cancel() + } + + cmd := exec.CommandContext(ctx, req.Command[0], req.Command[1:]...) + + if req.Cwd != "" { + cmd.Dir = req.Cwd + } + + if len(req.EnvVars) > 0 { + cmd.Env = os.Environ() + for k, v := range req.EnvVars { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v)) + } + } + + var stdout, stderr strings.Builder + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err := cmd.Run() + + resp := ProcessResponse{ + Stdout: stdout.String(), + Stderr: stderr.String(), + } + + if err != nil { + resp.Error = err.Error() + if exitErr, ok := err.(*exec.ExitError); ok { + resp.ExitCode = exitErr.ExitCode() + } else { + // If it's not an ExitError (e.g. command not found), set exit code to -1 or similar + resp.ExitCode = -1 + } + } else { + resp.ExitCode = 0 + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(resp) +} diff --git a/docs/api-guide.md b/docs/api-guide.md new file mode 100644 index 000000000..5c93cf38e --- /dev/null +++ b/docs/api-guide.md @@ -0,0 +1,171 @@ +# Substrate API Guide: WorkerPool & ActorTemplate + +This guide explains how to configure Substrate resources to deploy high-density, stateful agents. + +## 1. WorkerPool: The Physical Capacity + +The `WorkerPool` defines the pool of physical "warm" compute capacity. It manages a fleet of standby pods (herders) that are ready to receive and execute actor states. + +### Specification (`WorkerPoolSpec`) + +| Field | Type | Description | +| :--- | :--- | :--- | +| `replicas` | `int32` | **Required.** Number of physical standby pods to maintain in the cluster. | +| `ateomImage` | `string` | **Required.** The container image for the `ateom` herder process (e.g. `ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor`). | + +### Example + +```yaml +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: agent-pool + namespace: ate-demo +spec: + replicas: 10 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor +``` + +--- + +## 2. ActorTemplate: The Workload Blueprint + +The `ActorTemplate` defines the code, environment, and state-management policies for a specific type of agent. It is used to generate the "Golden Snapshot" from which all actors of this type are derived. + +### Specification (`ActorTemplateSpec`) + +| Field | Type | Description | +| :--- | :--- | :--- | +| `containers` | `[]Container` | **Required.** The workload definition (image, command, env, ports). | +| `workerPoolRef` | `ObjectReference` | **Required.** Pointer to the `WorkerPool` that provides the physical pods for this template. | +| `snapshotsConfig` | `SnapshotsConfig` | **Required.** GCS bucket and folder where memory snapshots are stored. | +| `pauseImage` | `string` | **Required.** The image used for the sandbox root (e.g. `gcr.io/gke-release/pause`). | +| `runsc` | `RunscConfig` | **Required.** Multi-platform configuration for fetching the gVisor binary. | + +### Workload Connectivity (Uniform DNS) +Substrate has standardized on a **Uniform DNS Mesh**. You no longer need to define `SessionDiscovery` rules. Every actor created from a template is automatically reachable through the **Substrate Router** via its unique ID: + +**Format:** `.actors.resources.substrate.ate.dev` + +### Example + +```yaml +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: secret-agent + namespace: ate-demo +spec: + runsc: + amd64: + # Note: These values are from the 2026-05-19 nightly. + # For the latest verified versions, see: manifests/counter/counter.yaml.tmpl + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: agent + image: gcr.io/my-project/my-agent:latest + command: ["/app/server"] + ports: + - containerPort: 80 + workerPoolRef: + name: agent-pool + namespace: ate-demo + snapshotsConfig: + location: gs://my-bucket/snapshots/secret-agent/ +``` + +--- + +## 3. Operational Workflow + +### The Golden Snapshot +When an `ActorTemplate` is created: +1. Substrate starts a temporary **Golden Pod**. +2. It executes your workload containers as defined in the template. +3. Once the process is initialized, gVisor takes a **Golden Snapshot** (Version 0). +4. The template enters the `Ready` phase. + +### Resumption Lifecycle +Once a template is `Ready`, creating an actor logically (via `kubectl-ate create actor`) allows it to be resumed instantly on any free worker in the referenced `WorkerPool`. Substrate bypasses the standard container boot and restores the process directly from its last saved state. + +--- + +## 4. Best Practices +* **Startup Logic:** Place expensive initialization (loading large models, establishing baseline connections) in your application's entry point. These will be captured in the Golden Snapshot and won't need to be repeated on every resumption. +* **Symmetry:** Ensure your `ActorTemplate` and `WorkerPool` are in the same namespace or have appropriate RBAC permissions to reference each other. +* **Version Management:** When updating code, create a new `ActorTemplate` (e.g. `v2`). Substrate treats each template as an immutable state root. + +--- + +## 5. Control Plane gRPC API + +The Substrate Control Plane (`ate-api-server`) exposes a gRPC interface for managing actors and workers. This is the primary API used by the `kubectl-ate` CLI and higher-level frameworks. + +### Service: `ateapi.Control` + +#### `CreateActor` +Registers a new logical actor in the system. +* **Request:** `CreateActorRequest` + * `actor_id`: Unique identifier (DNS-1123 label). + * `actor_template_namespace`: Namespace of the `ActorTemplate`. + * `actor_template_name`: Name of the `ActorTemplate`. +* **Response:** `CreateActorResponse` containing the initialized `Actor` object. + +#### `ResumeActor` +Activates a suspended actor by restoring it onto a physical worker. +* **Request:** `ResumeActorRequest` + * `actor_id`: ID of the actor to resume. + * `boot`: (Optional) If `true`, bypasses snapshots and performs a cold boot. +* **Response:** `ResumeActorResponse` containing the updated `Actor` object (including the physical `worker_ip`). + +#### `SuspendActor` +Hibernate a running actor, capturing its current RAM and disk state into a snapshot. +* **Request:** `SuspendActorRequest` + * `actor_id`: ID of the actor to suspend. +* **Response:** `SuspendActorResponse` containing the `Actor` object in `STATUS_SUSPENDED`. + +#### `DeleteActor` +Removes an actor from the registry. +* **Constraints:** Only actors in `STATUS_SUSPENDED` can be deleted. +* **Request:** `DeleteActorRequest` +* **Response:** `DeleteActorResponse` (empty). + +#### `GetActor` / `ListActors` +Query the state of logical actors. +* **GetActor:** Retrieves a single actor by ID. +* **ListActors:** Lists all actors currently tracked in the database. + +#### `ListWorkers` +Query the physical resource pool. +* **Request:** `ListWorkersRequest` +* **Response:** `ListWorkersResponse` containing a list of `Worker` objects (Pods) and their current assignment status. + +--- + +## 6. Advanced: Session Identity + +Workloads can exchange their ephemeral Kubernetes credentials for stable **Session Identity** credentials that persist even as the process migrates between different physical workers. + +### Service: `ateapi.SessionIdentity` +* **`MintJWT`:** Generates an OIDC-compatible JWT identifying the Substrate Actor. +* **`MintCert`:** Signs a Certificate Signing Request (CSR) to provide an mTLS identity for the actor. + +--- + +## 7. Framework & Ecosystem Integration + +Agent Substrate is designed to be the foundational execution layer for any agentic framework. + +### Agent Development Kit (ADK) +Substrate provides native support for ADK-compatible identities. Workloads can use the `SessionIdentity` service to mint JWTs that align with ADK's security model, ensuring seamless integration with ADK-managed tools and memory. + +### LangChain +Substrate is an ideal runtime for stateful LangChain agents. By defining a LangChain agent as an `ActorTemplate`, you can preserve the agent's internal "thought process" and conversation history in memory across hibernations, while sandboxing its tool execution for security. + +### Claude Code & CodeX +For developer-focused agents, Substrate enables massive multiplexing of coding environments. Each developer can have a dedicated, persistent terminal session (Actor) that preserves filesystem deltas, while the cluster only runs physical pods for active users. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 000000000..1db4fab92 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,401 @@ +# Agent Substrate Architecture + +NOTE: Much of this architecture is aspirational, and is not yet implemented! + +## Overview + +Agent Substrate is a system built on top of Kubernetes which manages agent-like +workloads to achieve high workload density and scale. It builds on top of +Kubernetes, but takes the Kubernetes control-plane out of the critical path to +achieve lower latency. Kubernetes provides the infrastructure provisioning and +management, while Agent Substrate provides agent-specific scheduling and +control. + +## Problem Statement + +Kubernetes is the industry standard platform for running modern workloads. It +is built to support a wide array of workloads, and it can scale to very large +clusters. Kubernetes is designed to handle tens- or hundreds-of-thousands of +relatively long-running workloads, but running agents at scale presents new +challenges. + +Agents and "agent-like" workloads are generally very bursty, spending most of +their time waiting for input or events, then handling those events, then going +back to waiting. The time they spend actually doing work is often very short, +and the time they spend waiting can be unbounded. Because they often run +untrusted logic, they are often run in sandboxes, which means they are usually +single-tenant instances, and there are a great many of them. + +Running these on Kubernetes presents a number of challenges: + * Idle Pods still consume resources. While Kubernetes is very scalable, + compute capacity is finite and has real costs. Whether we're talking about + CPU time, memory space, or just the number of Pods per node, agent-like + workloads are terrible for efficiency. + * The Kubernetes API server is not designed to handle millions of resources. + It excels at reconciling resources asynchronously across many controllers, + but it is not so good at storing very large numbers of discrete resources, + or for handling a huge volume of write traffic. + * Scheduling a workload on Kubernetes requires several asynchronous processes + to converge, plus several network hops, plus image pulling and other steps, + which can add up. Getting a Pod running in a couple of seconds is great + when that Pod will run for hours or days, but for a workload that will run + for milliseconds to low-digit seconds, that latency is unacceptable. + * State management is difficult. Kubernetes provides an API for managing + state (PersistentVolumes), but it is not designed for millions of volumes, + with widely varying amounts of data, being attached and detached at high + speed. + +## Core Concepts and Approaches + +Standard Kubernetes Pods are simply too heavy for many agentic workloads. + +### Terminology: "Actor" + +Agent Substrate seeks to solve these problems for "agent-like" workloads. +Often we simply say "agents", but it's important clarify that "agent-like" +workloads are not necessarily literally AI agents. In most of the docs we +instead use the term "actor" to refer to an instance of an agent-like workload. + +### Decoupling the Actor Lifecycle from Pods + +The obvious way to solve the problem of many idle Pods consuming resources is +to not have idle Pods - we need to get rid of them when they are idle, and +bring them back when they are needed. Suspend and resume is not a concept in +Kubernetes (yet!), but even if it was, the obvious way to implement it would +still run through the Kubernetes API server and scheduling subsystem, which is +(for now) too slow for our needs. + +Since many agents run untrusted code, we need to run them in sandboxes of some +sort. There are a number of sandboxing technologies available, notably +[gVisor](http://gvisor.dev) and micro-VMs such as +[Kata Containers](https://katacontainers.io/) are both popular options. Both +of those happen to support some notion of suspend and resume. + +Agent Substrate starts with suspend and resume. When an actor is idle, we +suspend it, which frees up the resources it was consuming. When an event comes +in that needs to be handled, we resume the actor. To avoid the latency of +going through the Kubernetes scheduler, we pre-start long-running "worker" +Pods, which are just sandboxes waiting for work. When an event comes in, we +assign it to a worker, which resumes the actor in that worker. We can now +multiplex a larger number of actors onto a smaller number of workers, which +allows us to achieve higher density and efficiency, while also reducing +latency. + +### A Focused Control Plane + +That doesn't solve the problem of the Kubernetes API server not being ready to +handle millions of resources. Unfortunately, there is no magic solution to +that. Instead of storing every actor, whether active or idle, as a Kubernetes +object, Agent Substrate includes a small, focused control-plane component which +is focused on high scale and QPS. It does not need the generality of the +Kubernetes API, which should allow it to be more effective for this use-case. + +### Agent-Aware Routing + +In order to achieve on-demand resuming of actors, we need to be able to trap and +inspect network traffic. Agent Substrate includes a lightweight, +substrate-aware network proxy which can inspect incoming traffic and trigger +the resumption of actors as needed. + +### New Problems + +Of course, there's no such thing as a free lunch, and these approaches have +trade-offs. + +First, we trade one problem (many idle Pods consuming resources) for another. +Doing suspend and resume at this scale introduces a vast data management +problem. We need to store the state of millions of actors, which can update +many times per second. Agent Substrate will need to consider data locality as +a first-class concern. When an event comes in, we need to know where the +actor's most recent state is stored, and either route the event to that +location or move the state to where the event can be serviced. + +In addition to that, we must acknowledge that building a new production-grade +control-plane component is a non-trivial effort. It will need to be highly +available, secure, and performant, and it will need to integrate well with +Kubernetes. + +Another problem to consider is observability and debugging. With actors being +multiplexed onto and off of workers all the time, it will be more difficult to +understand what is happening. Agent Substrate will need to provide robust +tooling for monitoring and debugging actors, including the ability to thread +together metrics and logs for an actor over time, to inspect the state of +suspended actors, and to trace the events that lead to their current state. + +### Problems We Haven't Addressed Yet + +As early as this project is, there are several problems that we haven't even +started to tackle yet, but which we know will need to be solved eventually. + + * Autoscaling: We will need to be able to automatically scale the number of workers up + and down based on demand. Kubernetes Pod autoscaling may be sufficient or + it might not. + * Peer to peer state sharing: Relying on data locality presents a risk of + data loss. We probably need some form of state-sharing to protect against + that, which needs to be balanced with saving state to a "permanent" store. + * Control plane authn/z: We will need to ensure that the control plane is secure, and that only + authorized users and agents can interact with it. + * Identity and policy: We know that agents' needs for identity are very + different than traditional workload identity and end-user credentials. + * There are certainly more that we haven't thought of yet! + +## North Star Metrics + +Agent Substrate is an ambitious effort. To keep us focused on the right +problems, we have identified a few north star metrics and targets. + + * Activation Latency: The time from when a wakeup event is received to when + the agent can receive traffic. + - Target: 100ms at 95th percentile + * Scale: The total number of agents, active and idle, that can be supported + in a single cluster. + - Target: 1 billion + * Throughput: The number of wakeup events that can be handled per second in + a single cluster. + - Target: 1000/second + +## Personas + +There are a few different personas that interact with the system: + + 1) **Cluster admins**: These are the people who own the Kubernetes cluster and + are responsible for its overall health and performance. If the Agent + Substrate needs more capacity, these are the folks who manage things like + cluster autoscaling, node provisioning, and so on. They probably don't + need to interact directly with the Agent Substrate much, if ever. + + 2) **Substrate admins**: These are the people who set up and own the Agent + Substrate instance(s) in a Kubernetes cluster. They are obviously aware + that it is running in a Kubernetes cluster, and are responsible for + configuring the Kubernetes resources for it (such as WarmPools). + + 3) **Agent developers**: These are the people who deploy agents into a substrate + for users or higher-level systems to consume. They might have to be aware + that they are using Kubernetes (some concepts are represented as CRDs, + such as ActorTemplates), or they might be using a higher level API which + itself uses Agent Substrate under the hood. + + 4) **Agent users**: These are the people who interact with agents running in the + substrate. They might be end-users of an application that is built on top + of Agent Substrate, or they might be higher-level systems that are using + Agent Substrate as a building block. They should not need to be aware that + they are using Kubernetes at all. + +## High-Level Design + +A substrate admin deploys the Agent Substrate into a Kubernetes cluster. They +configure the WorkerPool(s) that will be used to execute actors and prepare the +substrate's control-plane for use. Worker Pods are started, waiting for +assignments. + +An agent developer defines an ActorTemplate (a CR) which describes what it +means to instantiate that actor - what OCI image to run, how much memory it +needs, behavioral parameters, etc. The Agent Substrate uses that ActorTemplate +to create a "golden snapshot" of the actor, which will be used to fast-start +instances of that actor in the future. + +An agent user (or a higher-level system) makes a request to instantiate an +actor. They specify which ActorTemplate to use and other parameters. The +Agent Substrate creates an Actor record in its control-plane storage, which +tracks the state of that actor (suspended or running). + +When a request comes in for that actor instance, the Agent Substrate's proxy +intercepts the request. It looks in the control-plane to determine if that +actor is currently running or not. If not, it assigns the actor to a worker, +which involves telling a node-level component (the "atelet") to restore the +actor's most-recent snapshot into the worker on that node. The request is then +forwarded to the actor. + +Eventually, the user (or the higher-level system) is done with the actor, or it +has been idle for a while. It can request the Agent Substrate to suspend the +actor, taking a snapshot and freeing up the worker. The next time a request +comes in for that actor, it will be resumed again, possibly on a different +worker. + +## API Resource Models + +Agent Substrate categorizes resources into two groups based on their +persistence requirements and the frequency of state transitions. + +### System Configuration (Declarative/CRD-based) + +These resources define the intended state of the system and are managed via +Kubernetes CRD APIs. They are used for administrative operations and actor +environment definitions. + + * **WorkerPool**: Defines a pool of "warm" compute capacity. It specifies the + hardware shape (CPU, memory, accelerators), manages a fleet of standby + worker pods initialized and ready to receive resumed actor states. + + * **ActorTemplate**: An immutable definition of an actor-version. It + encapsulates the container image, configuration, and environment required + to generate a "golden" snapshot. + +### Dynamic Instance State (Database-based) + +These resources represent the high-frequency, ephemeral state of individual +actors and workers. They are stored in a high-performance, low-latency state +store (currently ValKey/Redis) to support real-time operations. + + * **Actor**: A specific instance of an ActorTemplate. An Actor record tracks + its globally unique identifier, physical location (Worker IP), current + status (RUNNING or SUSPENDED), and version-specific state metadata. + + * **Worker**: A representation of a worker pod in the WorkerPool. It tracks + the worker's unique identifier, current status (IDLE or BUSY), and the + Actor it is currently hosting (if any). + +### Architectural Rationale + +Agent Substrate utilizes this dual-layer model to optimize for both Reliability +and Performance: + + 1. **Scalability**: Offloading the high-frequency, high-scale management of + millions of actors to a specialized state store prevents overwhelming the + primary cluster control plane with thousands of updates per second. + + 2. **Latency**: Achieving 100ms resumption requires low-latency state + lookups and atomic worker assignments that bypass the eventual + consistency and variable latency of standard Kubernetes API servers. + + 3. **Governance**: Using Kubernetes objects for the environment (WorkerPools + and Templates) allows platform teams to apply familiar RBAC, auditing, + and policy enforcement to the underlying infrastructure. + +## System Components + +### Control Plane (`ate-api-server`) + +The brain of the system. It exposes a gRPC API for the data plane and CLI to +manage actor lifecycles. + + * **State Store**: Tracks the mapping of Actors to Workers in a + high-performance Redis store. + + * **Scheduler**: Selects a ready worker for a resumption request. + + * **Workflow Engine**: Orchestrates the multi-step Resume/Suspend sequences + (lock acquisition, storage download, sandbox restore). + +### Node Supervisor (`atelet` + `ateom`) + +The node-level subsystem manages the physical execution of sandboxes and the movement of snapshots. + + * **atelet**: A lightweight supervisor running on each node as a DaemonSet. It acts as the "Herder," managing a pool of physical pods and communicating with the Control Plane. + + * **ateom**: A specialized "interior gVisor" container image that runs inside the physical worker pods. It provides a gRPC interface for `atelet` to trigger `RunWorkload`, `CheckpointWorkload`, and `RestoreWorkload` operations. This separation ensures that the physical pod lifecycle remains decoupled from the sandboxed agent process. + + * **Lifecycle Management**: The `ateom` process invokes the sandbox runtime (e.g., `runsc` for gVisor) to checkpoint or restore processes within the physical pod boundaries. (Note: Substrate currently requires a `runsc` version with the `--allow-connected-on-save` flag to work around a bug in networking resumption during checkpointing). + + * **Storage Mover**: The `atelet` streams snapshots to and from GCS/S3, ensuring process state is persistent and portable across the cluster. + +### Networking Stack (`atenet` + Envoy) + +Handles session-aware routing and automatic re-animation. + + * **Uniform DNS Mesh**: Substrate provides a location-transparent actor discovery scheme via a global DNS suffix (`.actors.resources.substrate.ate.dev`). + + * **Routing**: The `atenet` router (powered by Envoy and an External Processing server) intercepts traffic destined for the mesh. It extracts the actor ID from the `Host` header, queries the Control Plane to determine the actor's current location, and triggers a `ResumeActor` workflow if the session is currently suspended. + + * **Latency**: The data plane is optimized for sub-100ms activation by bypassing Kubernetes' eventual consistency and performing atomic physical assignments. + +## Actor Lifecycle + +The lifecycle of an actor follows a state-driven sequence. + +### Phase 1: Creation (`CreateActor`) + +A user or framework calls `CreateActor` with a unique ID and a reference to an +`ActorTemplate`. + + * **Status**: The actor is registered in the database with status + `STATUS_SUSPENDED`. + + * **State**: The record is initialized in the database with the metadata and + **Golden Snapshot** (Version 0) reference derived from the associated + ActorTemplate. This ensures the actor can be instantly hydrated into a warm + worker upon its first request. + +### Phase 2: Activation (`ResumeActor`) + +Triggered by an inbound request at the Gateway or an explicit API call. + + 1. **Trigger**: The Gateway pauses the request and asks the Control Plane for + the actor's location. + + 2. **Assignment**: The Control Plane claims a warm worker from the + `WorkerPool`. + + 3. **Hydration**: The `atelet` supervisor coordinates with the `ateom` process inside the worker pod to restore the `GoldenSnapshot` (for first-run) or the `LastSnapshot` (for recurring runs) into the sandbox. + + 4. **Status**: Status transitions to `STATUS_RUNNING`. The actor now has an + active Worker IP. + + 5. **Response**: The Control Plane returns the worker IP to the Gateway, + which forwards the original request. + +### Phase 3: Hibernation (`SuspendActor`) + +Triggered by an explicit `SuspendActor` call. + + 1. **Checkpoint**: The `atelet` instructs `ateom` to freeze the process and capture a memory+disk snapshot. + + 2. **Persistence**: The `atelet` streams the snapshot from the pod to durable storage (e.g., GCS). + + 3. **Reclaim**: The physical worker is wiped and returned to the `WorkerPool`. + + 4. **Status**: Status transitions back to `STATUS_SUSPENDED`, now pointing to + the `LastSnapshot` for future resumptions. + +### Phase 4: Deletion + +Actors in `STATUS_SUSPENDED` status can be deleted from the Control Plane. +After deletion, the state of the actor (i.e., memory+disk snapshots) is garbage +collected. The garbage collection process is not implemented yet. + +## State Management & Persistence + +Agent Substrate distinguishes between two types of state, which are currently +captured together in a single versioned snapshot: + + 1. **Memory Snapshot**: The exact RAM state of the process. + + 2. **Working Volume (Disk)**: The files written to the container's writable + layer (the "working memory"). + +In the current implementation, both memory and disk states are tied to the +specific version of the code (ActorTemplate). This ensures strict consistency +during resumption. + +Snapshots are stored durably in **Google Cloud Storage (GCS)**. This model +allows the physical compute resources in the `WorkerPool` to be fully reclaimed +while an actor is idle, without losing any process or filesystem progress. + +## Security & Isolation + +Agent Substrate is built on a **Defense-in-Depth** model: + + * **Sandboxed Execution**: Every actor runs inside a hardened kernel-space + isolation layer (e.g. gVisor), preventing container escapes. + + * **Actor Identity**: Every interaction is powered by a unique, Agent + Substrate-managed identity that is independent of the underlying hardware. + This ensures that actors maintain their own granular permissions and + security context even as they migrate across physical nodes or code + versions. + + * **Request Authorization**: The system currently performs **Identity-Aware + Routing** by utilizing a uniform DNS routing scheme + (`.actors.resources.substrate.ate.dev`) + at the gateway to extract and validate actor identifiers from incoming traffic. This + ensures requests are only routed to recognized, registered actors. + Pluggable, granular authorization policies are planned for future + milestones. + + * **Network Policy**: Agent Substrate leverages standard Kubernetes + NetworkPolicy for connectivity control. Policies can be applied at the + `WorkerPool` boundary to restrict ingress/egress traffic for all actors + hosted within that pool. + + * **mTLS Everywhere**: All internal system communication (e.g., Control Plane + to Atelet) is secured via mutual TLS with short-lived certificates. diff --git a/docs/dev/best-practices/tracing.md b/docs/dev/best-practices/tracing.md new file mode 100644 index 000000000..c9c031d74 --- /dev/null +++ b/docs/dev/best-practices/tracing.md @@ -0,0 +1,265 @@ +# Tracing Best Practices + +This document outlines the tracing best practices for the Agent Substrate project using OpenTelemetry. + +## Why Do We Need Tracing? + +Tracing is important for debugging and performance optimization. It allows you to see how a request is processed and where it might be slow. + +## What is Tracing? + +Tracing is a way to track the flow of a request through a system. It allows you to see how long each step takes and where the bottlenecks are. + +Ideally, tracing outlines the entire flow of a request from the client to the server and back and includes all services that are invoked. + +Tracing consists of **spans** and **traces**. A span is a single operation, and a trace is a collection of spans that are related to each other. +Spans have a start and end time, and they can have attributes (key-value pairs) that provide additional information about the operation. +Traces have a trace ID and a span ID, which are used to identify the trace and the span. + +## How Tracing Works + +Tracing data is maintained in Golang's context object, which allows state to propagate through the call stack. + +When HTTP requests are made, tracing data may be included in the HTTP headers. For gRPC, tracing data is included in the metadata object. +Otel middleware handles both the extraction and injection of tracing data automatically. + +Servers have an exporter service that batches spans and pushes them to a remote collector for analysis. + +## Implementing Tracing + +### For servers + +All servers need to initialize an OpenTelemetry exporter and tracer provider. See `cmd/ateapi/ateapi.go:initTracing()` for an example: + +```go +func initTracing(ctx context.Context) (*sdktrace.TracerProvider, error) { + exporter, err := otlptracegrpc.New(ctx, + // GKE managed traces doesn't support validating the TLS certs of the collector + otlptracegrpc.WithInsecure(), + ) + if err != nil { + return nil, fmt.Errorf("failed to create OTLP exporter: %w", err) + } + + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.ServiceName("ateapi"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(res), + // Only trace on-demand when signaled by the client (e.g. via --trace flag) + sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.NeverSample())), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.TraceContext{}) + + return tp, nil +} +``` + +When calling the `initTracing()` function, be sure to `defer tp.Shutdown(ctx)` after the call to ensure that the tracer provider is properly shut down when the server exits: + +```go +defer func() { + if err := tp.Shutdown(ctx); err != nil { + slog.Error("Failed to shutdown TracerProvider", slog.Any("err", err)) + } +}() +``` + +Note the following important features: + +* We are not validating the TLS certs of the collector +* We provide a service name to exporter to identify which process is emitting the spans +* We only trace on-demand when desired by the client, as determined by the presence of tracing metadata/headers in the request + * For production, we will want to gate who/how tracing can be enabled for security purposes + +The YAML manifest for your server should include the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable to point the exporter to GKE's managed traces collector, e.g.: + +```yaml + containers: + - name: ateapi + image: ko://github.com/agent-substrate/substrate/cmd/servers/ateapi + ports: + - "443:443" + env: + # Tracing related environment variables + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: "http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317" +``` + +#### gRPC Servers +When implementing a gRPC server, you should include the following middleware to handle tracing: + +```go +server := grpc.NewServer( + grpc.StatsHandler(otelgrpc.NewServerHandler()) +) +``` + +#### HTTP Servers +When implementing an HTTP server, you should wrap the root multiplexer with `otelhttp.NewHandler`: + +```go +tracedMux := otelhttp.NewHandler( + mux, + "/", +) +``` + +While this model ensures all requests are eligible for tracing, it does not add the nature of the request to the span. As such, you should create a span in your handler to capture the nature of the request: + +```go +tracer := otel.Tracer("my-server-name") + +func someHandler(w http.ResponseWriter, r *http.Request) { + ctx, span := tracer.Start(r.Context(), "operationIdentifier") + defer span.End() + // ... rest of your handler +} +``` + +#### Sub-Spans +If you want to provide visibility into the internal workings of the server, you can create sub-spans at any point: + +```go +tracer := otel.Tracer("my-package-name") + +func someFunc(ctx) { + ctx, span := tracer.Start(ctx, "operationIdentifier") + defer span.End() +} +``` + +### For Clients + +Clients are not expected to instantiate an exporter, but they should give the option to include +tracing metadata in their requests to give users the ability to initiate a trace. + +#### Golang + +Like for servers, the tracer provider must be initialized and shutdown, but no exporter is required (note the sampler toggle): + +```go +func initTracing(ctx context.Context, enabled bool) (*sdktrace.TracerProvider, error) { + res, err := resource.New(ctx, + resource.WithAttributes( + semconv.UserAgentOriginal("my-client-name"), + ), + ) + if err != nil { + return nil, fmt.Errorf("failed to create resource: %w", err) + } + + sampler := sdktrace.NeverSample() + if enabled { + sampler = sdktrace.AlwaysSample() + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithResource(res), + sdktrace.WithSampler(sampler), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.TraceContext{}) + + return tp, nil +} +``` + +If your server is also a client, this step is redundant and can be omitted. + +Note that we are setting the UserAgentOriginal attribute here because we are assuming this is a user-facing client. +If this is a system service, we must set the ServiceName attribute instead. + +##### gRPC Clients + +When using a gRPC client, include the stats handler: + +```go +clientConn, err := grpc.NewClient( + serverAddr, + grpc.WithStatsHandler(otelgrpc.NewClientHandler()), +) +``` + +##### HTTP Clients + +For HTTP clients, add Otel's transport wrapper to your transport: + +```go +client := &http.Client{ + Transport: otelhttp.NewTransport(http.DefaultTransport), +} +``` + +#### Python + +Just like with Go, the provider must be initialized (note that because Python is only +used for load testing, we are using probability-based tracing): + +```python +from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.sampling import TraceIdRatioBased +from opentelemetry.sdk.resources import SERVICE_NAME, Resource +from opentelemetry.propagate import set_global_textmap, inject +from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator + +def init_tracing(): + sampler = TraceIdRatioBased(probability) + resource = Resource(attributes={ + SERVICE_NAME: "my-locust-service" + }) + provider = TracerProvider(sampler=sampler, resource=resource) + + trace.set_tracer_provider(provider) + set_global_textmap(TraceContextTextMapPropagator()) +``` + +##### gRPC Clients + +When using a gRPC client, simply instantiate a span and inject the headers, sending them as metadata: + +```python +from opentelemetry import trace +from opentelemetry.sdk.trace.sampling import TraceIdRatioBased +from opentelemetry.propagate import set_global_textmap, inject +from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator + +def call_with_trace(stub, method, request): + with tracer.start_as_current_span("operationIdentifier") as span: + headers = {} + inject(headers) + metadata = list(headers.items()) + response = stub.GetActor( + ateapi_pb2.GetActorRequest(actor_key=self.actor_key), + metadata=metadata + ) +``` + +##### HTTP Clients + +For HTTP clients, instantiate a span and inject the headers into the HTTP request: + +```python +from opentelemetry import trace +from opentelemetry.sdk.trace.sampling import TraceIdRatioBased +from opentelemetry.propagate import set_global_textmap, inject +from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator + +def call_with_trace(stub, method, request): + with tracer.start_as_current_span("operationIdentifier") as span: + headers = {} + inject(headers) + response = requests.get( + "http://example.com", + headers=headers + ) +``` diff --git a/docs/dev/valkey-direct-access.md b/docs/dev/valkey-direct-access.md new file mode 100644 index 000000000..ba8e38169 --- /dev/null +++ b/docs/dev/valkey-direct-access.md @@ -0,0 +1,6 @@ +# Accessing valkey directly + +Sometimes you need to access the valkey instance directly, you can do this with one "simple" command: + +1. `kubectl exec -n=ate-system -it valkey-cluster-0 -- valkey-cli -h valkey-cluster-service -c --tls --cacert /etc/valkey-ca/ca.crt --cer +t /run/servicedns.podcert.ate.dev/credential-bundle.pem --key /run/servicedns.podcert.ate.dev/credential-bundle.pem` diff --git a/docs/observability.md b/docs/observability.md new file mode 100644 index 000000000..fa3869668 --- /dev/null +++ b/docs/observability.md @@ -0,0 +1,103 @@ +# Actor Observability in Agent Substrate + +Agent Substrate manages actors as virtually long-lived entities that can be suspended when idle and resumed on different Kubernetes worker pods over time. + +This guide explains how Agent Substrate achieves observability across these suspend/resume cycles, allowing you to monitor logs, metrics, and traces as if an actor has been continuously running on a single dedicated machine. + +## The Observability Model + +To make underlying infrastructure transitions transparent, Agent Substrate establishes a standardized metadata model to identify actors across worker pods: +* `ate.dev/actor_id`: The unique identifier of the actor (e.g., `my-counter-1` or `test`). +* `ate.dev/actor_template`: The template used to create the actor (e.g., `counter`). +* `ate.dev/actor_namespace`: The Kubernetes namespace of the actor (e.g., `ate-demo-counter`). + +Currently, Agent Substrate automatically wraps container output and injects these metadata labels into **container logs**. For metrics and distributed tracing, Agent Substrate provides foundational system telemetry and on-demand request tracing, with roadmap plans to fully integrate actor-level correlation. + +--- + +## 1. Logging + +Agent Substrate captures container standard output/error, wraps them into structured JSON log entries, and injects the `ate.dev` metadata labels. + +### Active Actor Inspection via CLI +For quick, on-demand debugging of an active actor, use the Agent Substrate CLI: + +```bash +kubectl ate logs +``` + +> **Note:** `kubectl ate logs` queries the Kubernetes API of the worker pod where the actor is *currently* running. It is designed for immediate inspection of active actors. To view historical logs across past worker pods and suspension cycles, use a centralized logging backend. + +#### Example 1: Actor Not Currently Running +If an actor is suspended or not assigned to a worker pod, the CLI informs you immediately: + +```bash +$ kubectl ate logs test +Error: actor test is not currently running on any worker pod +``` + +#### Example 2: Default Pretty-Printed Output +When an active actor is assigned to a worker pod, the CLI formats the log stream for easy reading: + +```bash +$ kubectl ate logs test +[INFO] Actor started +[2026-05-19 18:39:24] [INFO] Starting server on port 80 +[2026-05-19 18:39:24] [INFO] Count +[2026-05-19 18:39:34] [INFO] Count +[2026-05-19 18:39:44] [INFO] Count +``` + +#### Example 3: Raw JSON Output (`--raw`) +To inspect the underlying structured JSON log entries, use the `--raw` flag. Note that during logging pipeline ingestion, the `ate.dev/` prefix is typically stripped from the label keys for cleaner indexing: + +```bash +$ kubectl ate logs test --raw +{"count":9,"fshash":"JiOzRUA5Ab+aro4YnhADSSMq8gUXhh/DMNSFzl75Q7c","level":"INFO","logging.googleapis.com/labels":{"actor_id":"test","actor_namespace":"ate-demo-counter","actor_template":"counter"},"msg":"Count","time":"2026-05-19T18:40:54.957798659Z"} +``` + +--- + +### Centralized Logging Backends (Multi-Dimensional Aggregation) +To view the continuous log history of actors across past and present worker pods, you can integrate Agent Substrate with any centralized logging backend (such as Grafana or Google Cloud Logging) that supports structured JSON indexing. + +Because the logging pipeline indexes the core metadata labels, you can query your logs across multiple dimensions using your logging platform's query language (examples below use Google Cloud Log Explorer syntax): + +#### 1. Actor-Centric View +To track the unified, continuous lifecycle of a single actor regardless of how many times it migrated across worker pods or was suspended/resumed: + +```text +labels.actor_id="test" +``` + +#### 2. Template-Centric View +To monitor or debug all actor instances created from a specific template (e.g., analyzing the collective behavior or error rates of all counter actors): + +```text +labels.actor_template="counter" +``` + +#### 3. Pod-Centric View +To inspect the physical worker pod's aggregate stream and see all co-located actors multiplexed together (useful for investigating pod-level resource exhaustion or noisy neighbor issues): + +```text +resource.labels.pod_name="counter-deployment-c995fdf4c-m7d96" +``` + +--- + +## 2. Metrics + +Agent Substrate currently emits foundational OpenTelemetry system and server metrics (such as `rpc.server.call.duration` and `http.server.request.duration`) to monitor the overall health and performance of the `ateapi` and `atelet` control plane services. + +> **Roadmap Note (Actor-Level Metrics):** A comprehensive metrics roadmap is under active development to support both system operators and workload analysis. Planned OpenTelemetry instrumentation focuses on control plane latency, state snapshot performance, fleet utilization density, and enriching metrics with standardized actor labels for seamless aggregation across pod transitions. + +--- + +## 3. Tracing + +Distributed tracing tracks the end-to-end flow of requests as they pass through the Agent Substrate gateway, router, worker pods, and external services. + +Currently, Agent Substrate supports on-demand request tracing. When initiated by a client (e.g., via the `--trace` flag), Agent Substrate leverages OpenTelemetry (OTel) for context propagation across the call stack. Each traced request generates a unique trace hash/ID, which you can use to inspect the detailed request lifecycle and span hierarchy inside Google Cloud Trace or Jaeger. + +> **Developer Guide:** For detailed instructions on configuring OpenTelemetry tracer providers, middleware, and exporters in your servers or clients, please refer to the [Tracing Best Practices](dev/best-practices/tracing.md) guide. diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 000000000..462a506ed --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,142 @@ +# Agent Substrate Roadmap + +## Overview + +Agent Substrate is a Kubernetes-based system for building multitenant applications based on independent, stateful container instances. Substrate builds on sandboxed, snapshottable Pods by adding the ability to update running containers in the Pod without invoking the Kubernetes scheduler. Substrate enables these containers to rapidly cycle between active and inactive lifecycle phases with fast suspend and resume from snapshots in inexpensive cloud object storage, without losing in-memory or filesystem state. This is especially critical for agentic workloads, which frequently oscillate between active (handling user input) and idle (waiting for LLMs or tool calls to complete). With Substrate, resources can be reclaimed during these idle moments for use by other workloads. This enables both greater efficiency and greater scale than using Pods alone, while still leveraging Kubernetes to provision capacity, configure networking and storage, and manage Substrate itself. + +This project is trying to move very quickly to find the right set of capabilities for the ever-changing agentic workloads market. Below are our priorities. Any efforts which are not aligned with these priorities should probably be deferred. + +1. Pinning down architectural decisions which influence the rest of these priorities. +2. Performance and reliability of wakeups, including suspend/resume and snapshot management. +3. A fast, scalable control-plane, including the storage layer, reliability, and security. +4. Useful identity, such that policies can be written in terms of identity. +5. Useful policy, including how users can specify ingress, egress, and peer networking. +6. Runtime modularity, such that different kinds of sandboxes (gVisor, microVMs, etc) can be used. + +Below is a collection of finer-grained efforts which we believe align with the above. + +## Coming Soon: High Priority + +### Actor Management (Compute) + +* Actor versioning via ActorTemplate (or new ActorDeployment API), with support for A/B testing and rollout strategies. +* Namespaces or a similar concept for grouping related actors together for both management and convenience of writing actor-to-actor authorization policy. +* Actor Forking/Cloning: Ability to branch a new logical actor from an existing checkpoint (the 'State Root') to support complex agent reasoning paths. +* Worker horizontal autoscaling: Ability to rapidly scale up nodes and warm Pods to meet actor demand. +* Clarify the actor lifecycle, including what data is retained across which events (e.g. gvisor upgrade \-\> loss of memory snapshot) +* Decide: What mode(s) of actor runs do we support? Can we prioritize and phase this? Assuming we always persist “working” data + * Clean start from OCI for every activation + * Resume from golden for every activation + * Persist rootfs (when possible), clean binary start for every activation + * Persist rootfs and memory (when possible), full process resume + +### Worker management + +* Worker class (e.g. free-tier on cheap hardware, premium on good hardware) +* Fungible worker pools (any worker in a class can run any actor in that class) + +### Control-plane + +* User authorization +* Good CLI + +### Networking + +* Actor security boundary implementation, default deny with explicit ACLs at scale with low latency. This overlaps with some of the security items (see below). +* Policy definition: between framework (outside) and Actors, between Actors, Actor Egress. +* Standardized DNS Mesh: Moving to a production-grade routing format (\.actors.resources.substrate.ate.dev) for location-transparent actor-to-actor communication. + +### Storage + +* Decide: Is Redis/ValKey the right answer for API storage? +* gVisor snapshot/resume optimizations + * storage tiering (local zswap, local SSD, peer-to-peer, blob) + * incremental snapshots +* Support for S3 (via plugin) +* Distinct lifecycle for “rootfs” and memory snapshots vs. “working” space. Needs API surface of where to mount. +* +* ConfigMaps as volumes +* Data locality in scheduling (needs to expose per-node available snapshots via API) + +### Security + +* Goal of two security boundaries between mutually untrusted actors that share the same Kubernetes node. +* Secure mTLS authentication and authorization between all system components. +* Secure actor-to-actor authentication and authorization policy that can be deployed in-band with actor lifecycle, maintaining low latency deployment. +* Ability to specify network policy for individual actors, including L7 protocol-aware filtering rules, that can be deployed in-band with actor lifecycle, maintaining low latency deployment. +* Credential injection, including actor identity, via proxies to eliminate exposure of cryptographic keys and bearer tokens to actors. +* Audit logging on API and lifecycle operations. +* Sandbox integrations for threat detection telemetry. +* Harden actor networking to further isolate from the surrounding node (e.g. with current networking +* Support for additional sandboxing technologies beyond gVisor, including at least one flavor of microVM. + +### Observability + +* Session-Aware Telemetry Correlation: Automated OTLP export where all logs, metrics, and traces are natively tagged with the Substrate Actor ID and worker ID. +* Prometheus metrics + +### Performance and Reliability + +* Representative workloads/traffic patterns +* Provisioning load test and benchmarking compute/infrastructure +* Storage and visualization for benchmark results +* Integrate debugging into load tests +* State Store Scale: Horizontal sharding support (via Redis Hash Tags) to enable management of 1M+ concurrent actors. +* Disk-Only Resume Policy: Support for cost-optimized hibernation where only the filesystem state is preserved, skipping the RAM restore for stateless or "cold" start-capable agents. + +### Testing + +* Support for local development and testing on KinD clusters. +* Define sufficient test matrices (what container system, clouds, other configuration knobs should be tested) +* Burn-in testing to detect memory/other resource leaks +* Mock LLMs/other dependencies + +### Integrations + +* Tight integration with Agent Executor for deploying AX on Kubernetes. +* Agent Development Kit (ADK) Native Support: Developing first-class bindings for ADK, allowing developers to build stateful agents that natively leverage Substrate’s lifecycle management and persistent working memory. +* LangChain Remote Execution Provider: A dedicated provider for LangChain to run complex, long-running agent tools in durable, sandboxed environments. +* Native MCP Server Hosting: Built-in support for deploying Model Context Protocol (MCP) servers as managed Substrate Actors, creating a secure tool ecosystem for any LLM. +* Actor-to-Actor (A2A) Calling Model: Standardized protocol for actors to discover and call other actors within the mesh via the gateway. +* Native MCP Tool Hosting: Ability to define and deploy standard Model Context Protocol (MCP) servers as managed Substrate Actors, providing a plug-and-play ecosystem for agentic tools. + +### Operability + +* Control-plane upgrades +* Worker upgrades +* Gvisor upgrades +* API schema changes +* Plan for growth from small to large (esp. wrt CP sharding) + +## Additional ideas we are thinking about + +### Actor Management (Compute) + +* Vertical worker autoscaling and IPPU (e.g. retain the memory/CPU config of the previous snapshot and update the worker pod when we assign an actor) +* Actor-\>worker selectors, taints, etc. +* Automated Garbage Collection: Background cleanup of idle actors based on configurable TTL + +### Storage + +* Policies to drive retention of old snapshots and controller(s) to do automated cleanups +* Peer-to-peer OCI and snapshot sharing +* K8s “projected” volumes, other than ConfigMap +* Storage model supported by external storage plugins (via CSI drivers?). +* Shared writeable storage across actors (e.g. an NFS volume). + +### Security + +* Ability for actors to delegate downscoped rights to children and peers. +* Image-pull credentials + +### Performance and Reliability + +* Shared image cache + +### Integrations + +* Stateful Coding Adapters: Standardized environment templates for Claude Code and CodeX to enable AI coding tasks that maintain persistent filesystem state across terminal sessions. + +### Administrative + +* Ability to run multiple substrates in a single cluster \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 000000000..50a858720 --- /dev/null +++ b/go.mod @@ -0,0 +1,171 @@ +module github.com/agent-substrate/substrate + +go 1.26.1 + +require ( + cloud.google.com/go/compute/metadata v0.9.0 + cloud.google.com/go/container v1.49.0 + cloud.google.com/go/iam v1.9.0 + cloud.google.com/go/resourcemanager v1.13.0 + cloud.google.com/go/serviceusage v1.14.0 + cloud.google.com/go/storage v1.62.1 + github.com/alicebob/miniredis/v2 v2.37.0 + github.com/aws/aws-sdk-go-v2 v1.41.7 + github.com/aws/aws-sdk-go-v2/config v1.32.17 + github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 + github.com/envoyproxy/go-control-plane v0.14.0 + github.com/envoyproxy/go-control-plane/envoy v1.37.0 + github.com/google/go-cmp v0.7.0 + github.com/google/go-containerregistry v0.21.5 + github.com/google/uuid v1.6.0 + github.com/hashicorp/go-reap v0.0.0-20260220095743-4e27870b4f51 + github.com/klauspost/compress v1.18.5 + github.com/opencontainers/runtime-spec v1.3.0 + github.com/prometheus/client_golang v1.23.2 + github.com/redis/go-redis/v9 v9.18.0 + github.com/spf13/cobra v1.10.2 + github.com/spf13/pflag v1.0.10 + github.com/vishvananda/netlink v1.3.1 + github.com/vishvananda/netns v0.0.5 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 + go.opentelemetry.io/otel v1.43.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 + go.opentelemetry.io/otel/exporters/prometheus v0.65.0 + go.opentelemetry.io/otel/sdk v1.43.0 + go.opentelemetry.io/otel/sdk/metric v1.43.0 + golang.org/x/oauth2 v0.36.0 + golang.org/x/sync v0.20.0 + golang.org/x/sys v0.43.0 + google.golang.org/api v0.274.0 + google.golang.org/grpc v1.81.0 + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af + k8s.io/api v0.35.3 + k8s.io/apiextensions-apiserver v0.35.0 + k8s.io/apimachinery v0.36.0-beta.0 + k8s.io/client-go v0.35.3 + k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 + sigs.k8s.io/controller-runtime v0.23.3 + sigs.k8s.io/yaml v1.6.0 +) + +require ( + cel.dev/expr v0.25.1 // indirect + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.19.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + cloud.google.com/go/longrunning v0.9.0 // indirect + cloud.google.com/go/monitoring v1.24.3 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.16 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 // indirect + github.com/aws/smithy-go v1.25.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/docker/cli v29.4.0+incompatible // indirect + github.com/docker/docker-credential-helpers v0.9.3 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect + github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.22.4 // indirect + github.com/go-openapi/jsonreference v0.21.4 // indirect + github.com/go-openapi/swag v0.25.4 // indirect + github.com/go-openapi/swag/cmdutils v0.25.4 // indirect + github.com/go-openapi/swag/conv v0.25.4 // indirect + github.com/go-openapi/swag/fileutils v0.25.4 // indirect + github.com/go-openapi/swag/jsonname v0.25.4 // indirect + github.com/go-openapi/swag/jsonutils v0.25.4 // indirect + github.com/go-openapi/swag/loading v0.25.4 // indirect + github.com/go-openapi/swag/mangling v0.25.4 // indirect + github.com/go-openapi/swag/netutils v0.25.4 // indirect + github.com/go-openapi/swag/stringutils v0.25.4 // indirect + github.com/go-openapi/swag/typeutils v0.25.4 // indirect + github.com/go-openapi/swag/yamlutils v0.25.4 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/gnostic-models v0.7.0 // indirect + github.com/google/pprof v0.0.0-20250602020802-c6617b811d0e // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/gax-go/v2 v2.21.0 // indirect + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/spdystream v0.5.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/onsi/ginkgo/v2 v2.27.4 // indirect + github.com/onsi/gomega v1.39.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/otlptranslator v1.0.0 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect + github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/vbatts/tar-split v0.12.2 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/detectors/gcp v1.42.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/term v0.41.0 // indirect + golang.org/x/text v0.35.0 // indirect + golang.org/x/time v0.15.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gotest.tools/v3 v3.5.2 // indirect + k8s.io/klog/v2 v2.140.0 // indirect + k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect + k8s.io/streaming v0.36.0-beta.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 000000000..c40bfb23e --- /dev/null +++ b/go.sum @@ -0,0 +1,401 @@ +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.19.0 h1:DGYwtbcsGsT1ywuxsIoWi1u/vlks0moIblQHgSDgQkQ= +cloud.google.com/go/auth v0.19.0/go.mod h1:2Aph7BT2KnaSFOM0JDPyiYgNh6PL9vGMiP8CUIXZ+IY= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/container v1.49.0 h1:K4nmtmJezHOzsIyedAOv1Ok36krw1apFmo4zXBaRL1A= +cloud.google.com/go/container v1.49.0/go.mod h1:EvqoT2eXfxLweXXUlhAMGR0sOAB00XPzEjoL01esSDs= +cloud.google.com/go/iam v1.9.0 h1:89wyjxT6DL4b5rk/Nk8eBC9DHqf+JiMstrn5IEYxFw4= +cloud.google.com/go/iam v1.9.0/go.mod h1:KP+nKGugNJW4LcLx1uEZcq1ok5sQHFaQehQNl4QDgV4= +cloud.google.com/go/logging v1.13.2 h1:qqlHCBvieJT9Cdq4QqYx1KPadCQ2noD4FK02eNqHAjA= +cloud.google.com/go/logging v1.13.2/go.mod h1:zaybliM3yun1J8mU2dVQ1/qDzjbOqEijZCn6hSBtKak= +cloud.google.com/go/longrunning v0.9.0 h1:0EzbDEGsAvOZNbqXopgniY0w0a1phvu5IdUFq8grmqY= +cloud.google.com/go/longrunning v0.9.0/go.mod h1:pkTz846W7bF4o2SzdWJ40Hu0Re+UoNT6Q5t+igIcb8E= +cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= +cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= +cloud.google.com/go/resourcemanager v1.13.0 h1:cc291PxLoKrHKVxqoJ2uMMzrxVJj+sRe+iEb1DFlDNA= +cloud.google.com/go/resourcemanager v1.13.0/go.mod h1:ve0VNxPoDU6XxDuEMCjkineb0YzXQXx3mOWwnNckGDE= +cloud.google.com/go/serviceusage v1.14.0 h1:2wVWxmoPU6zsMC0PUG5eOv34HNcGawrP98B1WqSaPKo= +cloud.google.com/go/serviceusage v1.14.0/go.mod h1:qUjKUDKkN+4yMmZfOaLleMRthZgGJgwDf72GmyuC6Gk= +cloud.google.com/go/storage v1.62.1 h1:Os0G3XbUbjZumkpDUf2Y0rLoXJTCF1kU2kWUujKYXD8= +cloud.google.com/go/storage v1.62.1/go.mod h1:cpYz/kRVZ+UQAF1uHeea10/9ewcRbxGoGNKsS9daSXA= +cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= +cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0/go.mod h1:IA1C1U7jO/ENqm/vhi7V9YYpBsp+IMyqNrEN94N7tVc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0 h1:7t/qx5Ost0s0wbA/VDrByOooURhp+ikYwv20i9Y07TQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 h1:0s6TxfCu2KHkkZPnBfsQ2y5qia0jl3MMrmBhu3nCOYk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/alicebob/miniredis/v2 v2.37.0 h1:RheObYW32G1aiJIj81XVt78ZHJpHonHLHW7OLIshq68= +github.com/alicebob/miniredis/v2 v2.37.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8= +github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10 h1:gx1AwW1Iyk9Z9dD9F4akX5gnN3QZwUB20GGKH/I+Rho= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.10/go.mod h1:qqY157uZoqm5OXq/amuaBJyC9hgBCBQnsaWnPe905GY= +github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU= +github.com/aws/aws-sdk-go-v2/config v1.32.17/go.mod h1:OXqUMzgXytfoF9JaKkhrOYsyh72t9G+MJH8mMRaexOE= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16 h1:r3RJBuU7X9ibt8RHbMjWE6y60QbKBiII6wSrXnapxSU= +github.com/aws/aws-sdk-go-v2/credentials v1.19.16/go.mod h1:6cx7zqDENJDbBIIWX6P8s0h6hqHC8Avbjh9Dseo27ug= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 h1:GpT/TrnBYuE5gan2cZbTtvP+JlHsutdmlV2YfEyNde0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23/go.mod h1:xYWD6BS9ywC5bS3sz9Xh04whO/hzK2plt2Zkyrp4JuA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 h1:bpd8vxhlQi2r1hiueOw02f/duEPTMK59Q4QMAoTTtTo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23/go.mod h1:15DfR2nw+CRHIk0tqNyifu3G1YdAOy68RftkhMDDwYk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 h1:FLudkZLt5ci0ozzgkVo8BJGwvqNaZbTWb3UcucAateA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9/go.mod h1:w7wZ/s9qK7c8g4al+UyoF1Sp/Z45UwMGcqIzLWVQHWk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15 h1:ieLCO1JxUWuxTZ1cRd0GAaeX7O6cIxnwk7tc1LsQhC4= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.15/go.mod h1:e3IzZvQ3kAWNykvE0Tr0RDZCMFInMvhku3qNpcIQXhM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 h1:pbrxO/kuIwgEsOPLkaHu0O+m4fNgLU8B3vxQ+72jTPw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23/go.mod h1:/CMNUqoj46HpS3MNRDEDIwcgEnrtZlKRaHNaHxIFpNA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23 h1:03xatSQO4+AM1lTAbnRg5OK528EUg744nW7F73U8DKw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.23/go.mod h1:M8l3mwgx5ToK7wot2sBBce/ojzgnPzZXUV445gTSyE8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0 h1:etqBTKY581iwLL/H/S2sVgk3C9lAsTJFeXWFDsDcWOU= +github.com/aws/aws-sdk-go-v2/service/s3 v1.101.0/go.mod h1:L2dcoOgS2VSgbPLvpak2NyUPsO1TBN7M45Z4H7DlRc4= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29h8BvsCoHQEQ6ST9X8w7w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk= +github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio= +github.com/aws/smithy-go v1.25.1 h1:J8ERsGSU7d+aCmdQur5Txg6bVoYelvQJgtZehD12GkI= +github.com/aws/smithy-go v1.25.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +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/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= +github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= +github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= +github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= +github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4= +github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80= +github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8= +github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4= +github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= +github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= +github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= +github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= +github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= +github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= +github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= +github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= +github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= +github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM= +github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= +github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= +github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= +github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= +github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= +github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= +github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= +github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= +github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= +github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= +github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= +github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= +github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= +github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= +github.com/google/go-containerregistry v0.21.5/go.mod h1:ySvMuiWg+dOsRW0Hw8GYwfMwBlNRTmpYBFJPlkco5zU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/pprof v0.0.0-20250602020802-c6617b811d0e h1:FJta/0WsADCe1r9vQjdHbd3KuiLPu7Y9WlyLGwMUNyE= +github.com/google/pprof v0.0.0-20250602020802-c6617b811d0e/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.21.0 h1:h45NjjzEO3faG9Lg/cFrBh2PgegVVgzqKzuZl/wMbiI= +github.com/googleapis/gax-go/v2 v2.21.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/hashicorp/go-reap v0.0.0-20260220095743-4e27870b4f51 h1:MpKgm7VEcOAD3dIR+cRoK4rbCcjqYXsMGCnFWTcHfds= +github.com/hashicorp/go-reap v0.0.0-20260220095743-4e27870b4f51/go.mod h1:qIFzeFcJU3OIFk/7JreWXcUjFmcCaeHTH9KoNyHYVCs= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y= +github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +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= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y= +github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= +github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs= +github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= +github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/detectors/gcp v1.42.0 h1:kpt2PEJuOuqYkPcktfJqWWDjTEd/FNgrxcniL7kQrXQ= +go.opentelemetry.io/contrib/detectors/gcp v1.42.0/go.mod h1:W9zQ439utxymRrXsUOzZbFX4JhLxXU4+ZnCt8GG7yA8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE= +go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0 h1:TC+BewnDpeiAmcscXbGMfxkO+mwYUwE/VySwvw88PfA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.43.0/go.mod h1:J/ZyF4vfPwsSr9xJSPyQ4LqtcTPULFR64KwTikGLe+A= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.274.0 h1:aYhycS5QQCwxHLwfEHRRLf9yNsfvp1JadKKWBE54RFA= +google.golang.org/api v0.274.0/go.mod h1:JbAt7mF+XVmWu6xNP8/+CTiGH30ofmCmk9nM8d8fHew= +google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0= +google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= +k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= +k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4= +k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU= +k8s.io/apimachinery v0.36.0-beta.0 h1:FioYxKfnvZuo0EUX/W9X0FhH3omaG7dEdtDk2IsfEtU= +k8s.io/apimachinery v0.36.0-beta.0/go.mod h1:AEUkaeqhot34WXPkRiWxszI4nUd8m40AAYi28N33hqc= +k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= +k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg= +k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= +k8s.io/streaming v0.36.0-beta.0 h1:F3nft77sAwteE5VgwkJQQQsdRqkPCBKk4O24W5bkvtk= +k8s.io/streaming v0.36.0-beta.0/go.mod h1:5Zm1U2Duu3uu1nG/ijKuwNWDkQk24aXVpScAhzRkzkk= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= +sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/ate-dev-env.sh.example b/hack/ate-dev-env.sh.example new file mode 100644 index 000000000..d79904a53 --- /dev/null +++ b/hack/ate-dev-env.sh.example @@ -0,0 +1,41 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Example environment variables for Substrate development. +# Copy this file to .ate-dev-env.sh and customize it for your environment. + +export PROJECT_ID=${USER}-gke-dev +export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") + +export GCE_REGION=us-central1 +export CLUSTER_LOCATION=us-central1-c + +export NETWORK=default +export SUBNETWORK=default + +export CLUSTER_NAME=substrate-poc +export CLUSTER_VERSION=1.35.0-gke.2398000 +export NODE_POOL_NAME=gvisor-pool +export NODE_POOL_VERSION=1.35.0-gke.2398000 +export GVISOR_NODE_MACHINE_TYPE=c3-standard-4 + +# Set this if you are using an existing cluster with a different context name. +export KUBECTL_CONTEXT= + +export BUCKET_NAME=snapshot-substrate-test-${PROJECT_ID} + +export KO_DOCKER_REPO="gcr.io/${PROJECT_ID}/ate-images" + +# Set this if you want to override the default build platforms +export KO_DEFAULTPLATFORMS=linux/amd64 diff --git a/hack/boilerplate/go.txt b/hack/boilerplate/go.txt new file mode 100644 index 000000000..dfc78e7ce --- /dev/null +++ b/hack/boilerplate/go.txt @@ -0,0 +1,14 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + diff --git a/hack/boilerplate/python.txt b/hack/boilerplate/python.txt new file mode 100644 index 000000000..0bee2e8a2 --- /dev/null +++ b/hack/boilerplate/python.txt @@ -0,0 +1,14 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/hack/boilerplate/yaml.txt b/hack/boilerplate/yaml.txt new file mode 100644 index 000000000..0bee2e8a2 --- /dev/null +++ b/hack/boilerplate/yaml.txt @@ -0,0 +1,14 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/hack/create-kind-cluster.sh b/hack/create-kind-cluster.sh new file mode 100755 index 000000000..56e743923 --- /dev/null +++ b/hack/create-kind-cluster.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit -o nounset -o pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +KIND_CLUSTER_NAME="${KIND_CLUSTER_NAME:-kind}" +reg_name="kind-registry" +reg_port="5001" + +mkdir -p "${ROOT}/bin" + +# 1. Create registry container unless it already exists +echo "Setting up local docker registry '${reg_name}' on port ${reg_port}..." +if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" == "true" ]; then + if ! docker port "${reg_name}" | grep -q "${reg_port}"; then + echo "Registry exists but is not mapped to port ${reg_port}. Recreating..." + docker rm -f "${reg_name}" + fi +fi + +if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != "true" ]; then + docker run \ + -d --restart=always \ + -p "127.0.0.1:${reg_port}:5000" \ + -p "[::1]:${reg_port}:5000" \ + --network bridge --name "${reg_name}" \ + registry:3 +fi + +# 2. Create kind configuration with containerdConfigPatches and feature gates +echo "Creating kind configuration for cluster '${KIND_CLUSTER_NAME}'..." +cat < "${ROOT}/bin/kind-config.yaml" +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane +# cmd/servers/podcertcontroller depends on ClusterTrustBundle & PodCertificateRequest. +# They are not enabled by default as of Kubernetes v1.36 +# https://github.com/kubernetes/kubernetes/blob/master/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +featureGates: + ClusterTrustBundle: true + ClusterTrustBundleProjection: true + PodCertificateRequest: true +runtimeConfig: + "certificates.k8s.io/v1beta1": "true" +EOF + +echo "Deleting existing kind cluster '${KIND_CLUSTER_NAME}' if it exists..." +kind delete cluster --name "${KIND_CLUSTER_NAME}" || true + +echo "Creating kind cluster '${KIND_CLUSTER_NAME}'..." +kind create cluster --name "${KIND_CLUSTER_NAME}" --config "${ROOT}/bin/kind-config.yaml" + +# 2.5 Enable Proxy ARP on kind nodes for gVisor loopback pod-to-pod networking +echo "Enabling Proxy ARP on kind nodes..." +for node in $(kind get nodes --name "${KIND_CLUSTER_NAME}"); do + docker exec "${node}" sysctl net.ipv4.conf.all.proxy_arp=1 +done + +# 3. Add the registry config to the nodes +echo "Adding registry config to kind nodes..." +REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}" +for node in $(kind get nodes --name "${KIND_CLUSTER_NAME}"); do + docker exec "${node}" mkdir -p "${REGISTRY_DIR}" + cat </dev/null 2>&1; then + "${demo_name}_usage" + fi + done +} + +run_kubectl() { + kubectl \ + ${KUBECTL_CONTEXT:+--context=${KUBECTL_CONTEXT}} \ + "$@" +} + +run_kubectl_ate() { + go run ./cmd/kubectl-ate \ + ${KUBECTL_CONTEXT:+--context=${KUBECTL_CONTEXT}} \ + "$@" +} + +run_ko() { + ./hack/ko.sh \ + "$@" \ + -- ${KUBECTL_CONTEXT:+--context=${KUBECTL_CONTEXT}} +} + +create_valkey_ca_certs_secret() { + log_step "create_valkey_ca_certs_secret" + local ca_certs="" + # Extract from in-cluster service-dns-ca-pool secret (base64 json) + local pool_json="" + pool_json=$(run_kubectl get secret -n podcertificate-controller-system service-dns-ca-pool -o jsonpath='{.data.pool}' | base64 --decode) + # Extract RootCertificateDER base64 string + local der_base64="" + der_base64=$(echo "${pool_json}" | grep -o '"RootCertificateDER":"[^"]*' | sed 's/"RootCertificateDER":"//') + # Convert DER to PEM certificate + ca_certs=$(echo "${der_base64}" | base64 --decode | openssl x509 -inform der -outform pem) + + run_kubectl create secret generic valkey-ca-certs \ + --from-literal=ca.crt="$(echo "${ca_certs}")" \ + -n ate-system \ + --dry-run=client -o yaml \ + | run_kubectl apply -f - +} + +create_jwt_authority_pool_secret() { + log_step "create_jwt_authority_pool_secret" + run_kubectl_ate admin make-jwt-pool \ + --key-id="1" \ + --name="session-id-jwt-pool" \ + --secret-namespace=ate-system +} + +create_session_id_ca_pool_secret() { + log_step "create_session_id_ca_pool_secret" + run_kubectl_ate admin make-ca-pool \ + --ca-id="1" \ + --name="session-id-ca-pool" \ + --secret-namespace=ate-system +} + +create_podcertificate_controller_cas() { + log_step "create_podcertificate_controller_cas" + run_kubectl create namespace podcertificate-controller-system || true + run_kubectl_ate admin make-ca-pool \ + --ca-id="1" \ + --name="service-dns-ca-pool" \ + --secret-namespace=podcertificate-controller-system + run_kubectl_ate admin make-ca-pool \ + --ca-id="1" \ + --name="pod-identity-ca-pool" \ + --secret-namespace=podcertificate-controller-system +} + +create_api_server_env_vars() { + log_step "create_api_server_env_vars" + run_kubectl create namespace ate-system --dry-run=client -o yaml \ + | run_kubectl apply -f - + + local redis_address="" + local use_iam_auth="true" + local tls_server_name="" + local client_cert="" + redis_address="valkey-cluster.ate-system.svc:6379" + use_iam_auth="false" + tls_server_name="valkey-cluster.ate-system.svc" + client_cert="/run/servicedns.podcert.ate.dev/credential-bundle.pem" + + echo "REDIS_ADDRESS: ${redis_address}" + + local jwt_issuer="" + if [[ -n "${PROJECT_ID:-}" && -n "${CLUSTER_LOCATION:-}" && -n "${CLUSTER_NAME:-}" ]]; then + jwt_issuer="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${CLUSTER_LOCATION}/clusters/${CLUSTER_NAME}" + else + jwt_issuer=$(run_kubectl get --raw /.well-known/openid-configuration 2>/dev/null | grep -o '"issuer":"[^"]*' | sed 's/"issuer":"//' || true) + if [[ -z "${jwt_issuer}" ]]; then + jwt_issuer="https://kubernetes.default.svc" + fi + fi + + run_kubectl create configmap -n ate-system ate-api-server-envvars \ + --from-literal=ATE_API_REDIS_ADDRESS="${redis_address}" \ + --from-literal=ATE_API_REDIS_USE_IAM_AUTH="${use_iam_auth}" \ + --from-literal=ATE_API_REDIS_TLS_SERVER_NAME="${tls_server_name}" \ + --from-literal=ATE_API_REDIS_CLIENT_CERT="${client_cert}" \ + --from-literal=ATE_API_K8SJWT_ISSUER="${jwt_issuer}" \ + --dry-run=client -o yaml \ + | run_kubectl apply -f - +} + +ensure_crds() { + log_step "ensure_crds" + if run_kubectl get crd workerpools.ate.dev actortemplates.ate.dev >/dev/null 2>&1; then + return + fi + + deploy_crds +} + +deploy_crds() { + log_step "deploy_crds" + go generate ./api/v1alpha1 ./internal/controllers + run_ko apply -f manifests/ate-install/generated +} + +deploy_ate_system() { + log_step "deploy_ate_system" + ensure_crds + + # Ensure namespace exists + run_kubectl apply -f manifests/ate-install/ate-system-namespace.yaml \ + && run_kubectl wait --for=jsonpath='{.status.phase}'=Active namespace/ate-system --timeout=60s + + ensure_apiserver_prerequisites + + go generate ./proto/ateapipb ./proto/ateletpb + + # Deploy podcertificate-controller first so it starts signing and creating trust bundles immediately + run_ko apply -f manifests/ate-install/pod-certificate-controller.yaml + run_kubectl rollout status deployment/podcertificate-controller -n podcertificate-controller-system --timeout=120s + + # Wait for both ClusterTrustBundles to be created by the controller + echo "Waiting for podcertificate ClusterTrustBundles to be ready..." + until run_kubectl get clustertrustbundles podidentity.podcert.ate.dev:identity:primary-bundle >/dev/null 2>&1; do + sleep 1 + done + until run_kubectl get clustertrustbundles servicedns.podcert.ate.dev:identity:primary-bundle >/dev/null 2>&1; do + sleep 1 + done + + local manifests="" + if [[ "${ATE_INSTALL_KIND:-false}" == "true" ]]; then + # Build everything resolved with Kustomize for Kind + manifests=$(kubectl kustomize manifests/ate-install/kind --load-restrictor LoadRestrictionsNone | run_ko resolve -f -) + else + # Build everything resolved with base manifests for GKE + manifests=$(run_ko resolve -f manifests/ate-install) + fi + echo "${manifests}" | run_kubectl apply -f - +} + +# Ensure secrets and configmaps required by ate-apiserver +ensure_apiserver_prerequisites() { + log_step "ensure_apiserver_prerequisites" + run_kubectl get secret -n ate-system session-id-jwt-pool >/dev/null 2>&1 \ + || create_jwt_authority_pool_secret + run_kubectl get secret -n ate-system session-id-ca-pool >/dev/null 2>&1 \ + || create_session_id_ca_pool_secret + run_kubectl get secret -n podcertificate-controller-system service-dns-ca-pool >/dev/null 2>&1 \ + || create_podcertificate_controller_cas + run_kubectl get secret -n ate-system valkey-ca-certs >/dev/null 2>&1 \ + || create_valkey_ca_certs_secret + run_kubectl get configmap -n ate-system ate-api-server-envvars >/dev/null 2>&1 \ + || create_api_server_env_vars +} + +# Redeploy only the ate-apiserver +deploy_ate_apiserver() { + log_step "deploy_ate_apiserver" + ensure_crds + + go generate ./proto/ateapipb ./proto/ateletpb + + # Ensure namespace exists + run_kubectl apply -f manifests/ate-install/ate-system-namespace.yaml \ + && run_kubectl wait --for=jsonpath='{.status.phase}'=Active namespace/ate-system --timeout=60s + + ensure_apiserver_prerequisites + + run_ko apply -f manifests/ate-install/ate-api-server.yaml +} + +deploy_atelet() { + log_step "deploy_atelet" + ensure_crds + + go generate ./proto/ateapipb ./proto/ateletpb + + # Ensure namespace exists + run_kubectl apply -f manifests/ate-install/ate-system-namespace.yaml \ + && run_kubectl wait --for=jsonpath='{.status.phase}'=Active namespace/ate-system --timeout=60s + + local manifest="" + if [[ "${ATE_INSTALL_KIND:-false}" == "true" ]]; then + # Use Kustomize to build and resolve the atelet DaemonSet patch + manifest=$(kubectl kustomize manifests/ate-install/kind/atelet --load-restrictor LoadRestrictionsNone | run_ko resolve -f -) + else + # Use base manifest for GKE + manifest=$(run_ko resolve -f manifests/ate-install/atelet.yaml) + fi + echo "${manifest}" | run_kubectl apply -f - +} + +deploy_atenet() { + log_step "deploy_atenet" + ensure_crds + + go generate ./proto/ateapipb ./proto/ateletpb + + # Ensure namespace exists + run_kubectl apply -f manifests/ate-install/ate-system-namespace.yaml \ + && run_kubectl wait --for=jsonpath='{.status.phase}'=Active namespace/ate-system --timeout=60s + + run_ko apply -f manifests/ate-install/atenet-router.yaml + run_ko apply -f manifests/ate-install/atenet-dns.yaml +} + +delete_ate_system() { + log_step "delete_ate_system" + if [[ "${ATE_INSTALL_RUSTFS:-false}" == "true" ]]; then + run_kubectl delete --ignore-not-found -f manifests/ate-install/kind/rustfs.yaml + fi + run_kubectl delete --ignore-not-found -f manifests/ate-install + run_kubectl delete --ignore-not-found -f manifests/ate-install/generated +} + +delete_atenet() { + log_step "delete_atenet" + run_kubectl delete --ignore-not-found -f manifests/ate-install/atenet-router.yaml +} + +delete_all() { + log_step "delete_all" + for demo_name in "${ATE_DEMOS[@]}"; do + if declare -F "${demo_name}_delete" >/dev/null 2>&1; then + "${demo_name}_delete" + fi + done + delete_ate_system +} + +if [ "$#" -eq 0 ]; then + usage + exit 1 +fi + +# If -h or --help appears anywhere in the command line, print the usage and exit. +for arg in "$@"; do + case "$arg" in + -h|--help) + usage + exit 0 + ;; + esac +done + +while [[ "$#" -gt 0 ]]; do + # Run ${demo}_cmdline if it exists. If it returns 0, then we successfully + # handled this argument and can continue. Otherwise, fallthrough to check + # the other arguments. + for demo_name in "${ATE_DEMOS[@]}"; do + if declare -F "${demo_name}_cmdline" >/dev/null 2>&1; then + if "${demo_name}_cmdline" "$1"; then + shift + continue 2 + fi + fi + done + + case $1 in + --deploy-ate-system) deploy_ate_system ;; + --delete-ate-system) delete_ate_system ;; + --delete-all) delete_all ;; + + --deploy-atelet) deploy_atelet ;; + --deploy-ate-apiserver) deploy_ate_apiserver ;; + + --deploy-atenet) deploy_atenet ;; + --delete-atenet) delete_atenet ;; + + --create-jwt-authority-pool-secret) create_jwt_authority_pool_secret ;; + --create-session-id-ca-pool-secret) create_session_id_ca_pool_secret ;; + --create-podcertificate-controller-cas) create_podcertificate_controller_cas ;; + --create-valkey-ca-certs-secret) create_valkey_ca_certs_secret ;; + --create-api-server-env-vars) create_api_server_env_vars ;; + + *) + # Invalid option, should usage and exit with an error. + echo "Error: unknown option: $1" >&2 + echo "" + usage + exit 1 + ;; + esac + shift +done diff --git a/hack/install-demo-agent-secret.sh b/hack/install-demo-agent-secret.sh new file mode 100644 index 000000000..b61be90c0 --- /dev/null +++ b/hack/install-demo-agent-secret.sh @@ -0,0 +1,41 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is sourced as part of install-ate.sh. Do not run directly. + +ATE_DEMOS+=(demo-agent-secret) # register demo-agent-secret + +demo-agent-secret_cmdline() { + case "${1}" in + --deploy-demo-agent-secret) demo-agent-secret_deploy ;; + --delete-demo-agent-secret) demo-agent-secret_delete ;; + *) + return 1 + ;; + esac + return 0 +} + +demo-agent-secret_deploy() { + log_step "demo-agent-secret_deploy" + ensure_crds + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" manifests/agent-secret/agent-secret.yaml.tmpl \ + | run_ko apply -f - +} + +demo-agent-secret_delete() { + log_step "demo-agent-secret_delete" + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" manifests/agent-secret/agent-secret.yaml.tmpl \ + | run_kubectl delete --ignore-not-found -f - +} diff --git a/hack/install-demo-claude-code-multiplex.sh b/hack/install-demo-claude-code-multiplex.sh new file mode 100644 index 000000000..44ce27913 --- /dev/null +++ b/hack/install-demo-claude-code-multiplex.sh @@ -0,0 +1,97 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is sourced as part of install-ate.sh. Do not run directly. + +ATE_DEMOS+=(demo-claude-code-multiplex) # register demo-claude-code-multiplex + +demo-claude-code-multiplex_cmdline() { + case "${1}" in + --deploy-demo-claude-code-multiplex) demo-claude-code-multiplex_deploy ;; + --delete-demo-claude-code-multiplex) demo-claude-code-multiplex_delete ;; + *) + return 1 + ;; + esac + return 0 +} + +# Build the workload image, push to ${KO_DOCKER_REPO}, and echo the resolved +# digest-pinned reference (e.g. gcr.io/.../claude-multiplex-demo-workload@sha256:...). +# The workload is a Dockerfile-based Python+Claude-Code wrapper (not a Go +# binary), so it uses docker buildx rather than ko. +demo-claude-code-multiplex_build_workload() { + local repo="${KO_DOCKER_REPO}/claude-multiplex-demo-workload" + local stage_tag="${repo}:build-$(date +%s)" + docker buildx build \ + --platform=linux/amd64 \ + --push \ + -t "${stage_tag}" \ + demos/claude-code-multiplex/workload >&2 + local digest + digest=$(docker buildx imagetools inspect "${stage_tag}" --format '{{json .}}' \ + | jq -r '.manifest.digest') + if [[ -z "${digest}" || "${digest}" == "null" ]]; then + echo "Failed to resolve workload image digest from ${stage_tag}" >&2 + return 1 + fi + echo "${repo}@${digest}" +} + +demo-claude-code-multiplex_deploy() { + log_step "demo-claude-code-multiplex_deploy" + if [[ -z "${ANTHROPIC_API_KEY:-}" ]]; then + echo "ANTHROPIC_API_KEY must be set" >&2 + return 1 + fi + if [[ -z "${BUCKET_NAME:-}" ]]; then + echo "BUCKET_NAME must be set" >&2 + return 1 + fi + if [[ -z "${KO_DOCKER_REPO:-}" ]]; then + echo "KO_DOCKER_REPO must be set (see hack/ate-dev-env.sh.example)" >&2 + return 1 + fi + + local workload_image + workload_image=$(demo-claude-code-multiplex_build_workload) + if [[ -z "${workload_image}" ]]; then + return 1 + fi + log_step " workload image: ${workload_image}" + + sed -e "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" \ + -e "s|\${ANTHROPIC_API_KEY}|${ANTHROPIC_API_KEY}|g" \ + -e "s|\${WORKLOAD_IMAGE}|${workload_image}|g" \ + manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl \ + | run_kubectl apply -f - +} + +demo-claude-code-multiplex_delete() { + log_step "demo-claude-code-multiplex_delete" + # Delete-time substitution doesn't need a real image — k8s identifies + # resources by metadata, not container spec. Use placeholders so sed + # produces valid YAML even when the env vars aren't set. + sed -e "s|\${BUCKET_NAME}|${BUCKET_NAME:-placeholder}|g" \ + -e "s|\${ANTHROPIC_API_KEY}|${ANTHROPIC_API_KEY:-placeholder}|g" \ + -e "s|\${WORKLOAD_IMAGE}|placeholder|g" \ + manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl \ + | run_kubectl delete --ignore-not-found -f - +} + +demo-claude-code-multiplex_usage() { + echo "" + echo " Required env: ANTHROPIC_API_KEY, BUCKET_NAME, KO_DOCKER_REPO" + echo " See demos/claude-code-multiplex/README.md for the walkthrough." +} diff --git a/hack/install-demo-counter.sh b/hack/install-demo-counter.sh new file mode 100644 index 000000000..ebd871a1e --- /dev/null +++ b/hack/install-demo-counter.sh @@ -0,0 +1,41 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is sourced as part of install-ate.sh. Do not run directly. + +ATE_DEMOS+=(demo-counter) # register demo-counter + +demo-counter_cmdline() { + case "${1}" in + --deploy-demo-counter) demo-counter_deploy ;; + --delete-demo-counter) demo-counter_delete ;; + *) + return 1 + ;; + esac + return 0 +} + +demo-counter_deploy() { + log_step "demo-counter_deploy" + ensure_crds + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" manifests/counter/counter.yaml.tmpl \ + | run_ko apply -f - +} + +demo-counter_delete() { + log_step "demo-counter_delete" + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" manifests/counter/counter.yaml.tmpl \ + | run_kubectl delete --ignore-not-found -f - +} diff --git a/hack/install-demo-sandbox.sh b/hack/install-demo-sandbox.sh new file mode 100644 index 000000000..83fd720a0 --- /dev/null +++ b/hack/install-demo-sandbox.sh @@ -0,0 +1,41 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This is sourced as part of install-ate.sh. Do not run directly. + +ATE_DEMOS+=(demo-sandbox) # register demo-sandbox + +demo-sandbox_cmdline() { + case "${1}" in + --deploy-demo-sandbox) demo-sandbox_deploy ;; + --delete-demo-sandbox) demo-sandbox_delete ;; + *) + return 1 + ;; + esac + return 0 +} + +demo-sandbox_deploy() { + log_step "demo-sandbox_deploy" + ensure_crds + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" manifests/sandbox/sandbox.yaml.tmpl \ + | run_ko apply -f - +} + +demo-sandbox_delete() { + log_step "demo-sandbox_delete" + sed "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" manifests/sandbox/sandbox.yaml.tmpl \ + | run_kubectl delete --ignore-not-found -f - +} diff --git a/hack/ko.sh b/hack/ko.sh new file mode 100755 index 000000000..bca7808f3 --- /dev/null +++ b/hack/ko.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit -o nounset -o pipefail + +ROOT=$(git rev-parse --show-toplevel) +"${ROOT}"/hack/run-tool.sh ko "$@" diff --git a/hack/protoc.sh b/hack/protoc.sh new file mode 100755 index 000000000..d2d7acd49 --- /dev/null +++ b/hack/protoc.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +# pin protoc version and binary hashes +PROTOC_VERSION="25.3" +linux_x86_64_EXPECTED_SHA="f853e691868d0557425ea290bf7ba6384eef2fa9b04c323afab49a770ba9da80" +linux_aarch_64_EXPECTED_SHA="9eae1f20f70cccc912d1c318c3929b86aebf5afd4b0f32c196ef682c222ed5ae" +osx_x86_64_EXPECTED_SHA="247e003b8e115405172eacc50bd19825209d85940728e766f0848eee7c80e2a1" +osx_aarch_64_EXPECTED_SHA="d0fcd6d3b3ef6f22f1c47cc30a80c06727e1eccdddcaf0f4a3be47c070ffd3fe" + +# Determine OS and Arch for protoc release +# Standard releases: linux-x86_64, osx-x86_64, osx-aarch_64 +OS_NAME=$(uname -s | tr '[:upper:]' '[:lower:]') +ARCH_NAME=$(uname -m) + +if [ "$OS_NAME" = "darwin" ]; then + if [ "$ARCH_NAME" = "x86_64" ]; then + PROTOC_PLATFORM="osx-x86_64" + else + PROTOC_PLATFORM="osx-aarch_64" + fi +else + + if [ "$ARCH_NAME" = "x86_64" ]; then + PROTOC_PLATFORM="linux-x86_64" + elif [ "$ARCH_NAME" = "aarch64" ] || [ "$ARCH_NAME" = "arm64" ]; then + PROTOC_PLATFORM="linux-aarch_64" + fi +fi + +# Target folder for local protoc binary +OUT_DIR="$(dirname "$0")/../bin/protoc-install" +PROTOC_BIN="$OUT_DIR/bin/protoc" + + +if [ ! -f "$PROTOC_BIN" ]; then + echo "Downloading protoc v${PROTOC_VERSION} for ${PROTOC_PLATFORM}..." + mkdir -p "$OUT_DIR" + URL="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${PROTOC_PLATFORM}.zip" + + case "$PROTOC_PLATFORM" in + "linux-x86_64") EXPECTED_SHA="${linux_x86_64_EXPECTED_SHA}";; + "linux-aarch_64") EXPECTED_SHA="${linux_aarch_64_EXPECTED_SHA}";; + "osx-x86_64") EXPECTED_SHA="${osx_x86_64_EXPECTED_SHA}";; + "osx-aarch_64") EXPECTED_SHA="${osx_aarch_64_EXPECTED_SHA}";; + *) echo "Unknown platform $PROTOC_PLATFORM"; exit 1 ;; + esac + + # Download and verify + curl -sSL "$URL" -o "$OUT_DIR/protoc.zip" + ACTUAL_SHA=$(shasum -a 256 "$OUT_DIR/protoc.zip" | awk '{print $1}') + if [ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]; then + echo "Checksum verification failed for protoc download!" + echo "Expected: $EXPECTED_SHA" + echo "Got: $ACTUAL_SHA" + exit 1 + fi + + unzip -q -o "$OUT_DIR/protoc.zip" -d "$OUT_DIR" + rm -f "$OUT_DIR/protoc.zip" + chmod +x "$PROTOC_BIN" + echo "Local protoc installed at $PROTOC_BIN" +fi + + +exec "$PROTOC_BIN" "$@" diff --git a/hack/run-e2e.sh b/hack/run-e2e.sh new file mode 100755 index 000000000..cf336544a --- /dev/null +++ b/hack/run-e2e.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e +set -u +set -o pipefail + +ROOT=$(git rev-parse --show-toplevel) +cd "${ROOT}" + +if [[ -r .ate-dev-env.sh ]] && [[ -z "${NO_DEV_ENV:-}" ]]; then + source .ate-dev-env.sh +fi + +show_help() { + cat < Run only tests matching regexp + -v Verbose output + -count n Run tests n times + +See "go help testflag" for more Go test flags. +EOF +} + +target_path="./internal/e2e/suites/..." + +if [[ "$#" -gt 0 ]]; then + if [[ "$1" == "-h" || "$1" == "--help" ]]; then + show_help + exit 0 + fi + + if [[ "$1" == "./internal/e2e"* || "$1" == "internal/e2e"* ]]; then + target_path="$1" + shift + elif [[ "$1" == -* ]]; then + # It's a flag, keep default target_path, don't shift + : + else + echo "Error: Invalid target path '$1'." >&2 + echo "The first argument must be a valid E2E path starting with './internal/e2e' or a flag starting with '-'." >&2 + echo "Use '$0 -h' for help." >&2 + exit 1 + fi +fi + +go_test_args=() +e2e_args=() +found_args_sep=false + +for arg in "$@"; do + if [[ "$arg" == "-h" || "$arg" == "--help" ]]; then + show_help + exit 0 + fi + if [[ "$arg" == "-args" ]]; then + found_args_sep=true + continue + fi + + if [[ "$found_args_sep" == "true" ]]; then + e2e_args+=("$arg") + else + go_test_args+=("$arg") + fi +done + +extra_e2e_args=() +if [[ -n "${KUBECTL_CONTEXT:-}" ]]; then + extra_e2e_args+=("-kube-context" "${KUBECTL_CONTEXT}") +fi + +exec go test -v "$target_path" "${go_test_args[@]}" -args -e2e "${extra_e2e_args[@]}" "${e2e_args[@]}" + diff --git a/hack/run-tool.sh b/hack/run-tool.sh new file mode 100755 index 000000000..29496a9ba --- /dev/null +++ b/hack/run-tool.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit -o nounset -o pipefail + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 [--print-bin-path] [args...]" >&2 + exit 1 +fi + +PRINT_PATH=false +if [ "$1" = "--print-bin-path" ]; then + PRINT_PATH=true + shift +fi + +TOOL_NAME="$1" +shift + +ROOT="$(git rev-parse --show-toplevel)" +case "${TOOL_NAME}" in + "client-gen"|"informer-gen"|"lister-gen") + TOOL_DIR="${ROOT}/hack/tools/code-generator" + ;; + *) + TOOL_DIR="${ROOT}/hack/tools/${TOOL_NAME}" + ;; +esac + +TOOL_BIN="$(cd "${TOOL_DIR}" && go tool -n "${TOOL_NAME}")" + +if [ "${PRINT_PATH}" = true ]; then + echo -n "${TOOL_BIN}" + exit 0 +fi + +# Run the tool binary from original CWD +exec "${TOOL_BIN}" "$@" diff --git a/hack/teardown.sh b/hack/teardown.sh new file mode 100755 index 000000000..3ebddc62c --- /dev/null +++ b/hack/teardown.sh @@ -0,0 +1,123 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eu + +# Source the environment variables +if [ -f .ate-dev-env.sh ]; then + source .ate-dev-env.sh +else + echo "Please create .ate-dev-env.sh from the example file in hack" + exit 1 +fi + +# Precheck for cluster-admin permissions +kubectl auth can-i delete crd 2>/dev/null | grep -q yes || { + echo "teardown requires cluster-admin on the GKE cluster" >&2 + exit 1 +} + +# --- Helper Functions --- +function usage() { + echo "Usage: $0 [options]" + echo "Options:" + echo " --revoke-gke-node-permissions Revoke GKE nodes permission to pull images" + echo " --delete-iam-policy-bindings Delete IAM policy bindings for atelet" + echo " --delete-snapshot-bucket Delete snapshot bucket" + echo " --delete-gvisor-node-pool Delete gVisor node pool" + echo " --delete-cluster Delete GKE cluster" + echo " --all Run all teardown steps (reverse order of setup)" + exit 1 +} + +# --- Teardown Functions --- + +# Revoke GKE Node Permissions (Reverse of grant_gke_node_permissions) +revoke_gke_node_permissions() { + echo "Revoking GKE node permissions..." + gcloud projects remove-iam-policy-binding "${PROJECT_ID}" \ + --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \ + --role="roles/storage.objectViewer" \ + --condition=None \ + --quiet || true + gcloud projects remove-iam-policy-binding "${PROJECT_ID}" \ + --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \ + --role="roles/artifactregistry.reader" \ + --condition=None \ + --quiet || true +} + +# Delete IAM Policy Bindings for Bucket (Reverse of create_iam_policy_bindings) +delete_iam_policy_bindings() { + echo "Deleting IAM policy bindings for bucket..." + gcloud storage buckets remove-iam-policy-binding "gs://${BUCKET_NAME}" \ + --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/ate-system/sa/atelet" \ + --role="roles/storage.objectAdmin" \ + --quiet || true + gcloud storage buckets remove-iam-policy-binding "gs://${BUCKET_NAME}" \ + --member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/ate-system/sa/atelet" \ + --role="roles/storage.bucketViewer" \ + --quiet || true +} + +# Delete Snapshot Bucket (Reverse of create_snapshot_bucket) +delete_snapshot_bucket() { + echo "Deleting snapshot bucket..." + gcloud storage rm --recursive "gs://${BUCKET_NAME}/**" --project="${PROJECT_ID}" --quiet || true + gcloud storage buckets delete "gs://${BUCKET_NAME}" --project="${PROJECT_ID}" --quiet || true +} + +# Delete gVisor Node Pool (Reverse of create_gvisor_node_pool) +delete_gvisor_node_pool() { + echo "Deleting gVisor node pool..." + gcloud container node-pools delete "${NODE_POOL_NAME}" \ + --cluster="${CLUSTER_NAME}" \ + --location="${CLUSTER_LOCATION}" \ + --project="${PROJECT_ID}" \ + --quiet || true +} + +# Delete Cluster (Reverse of create_cluster) +delete_cluster() { + echo "Deleting GKE cluster..." + gcloud container clusters delete "${CLUSTER_NAME}" \ + --location="${CLUSTER_LOCATION}" \ + --project="${PROJECT_ID}" \ + --quiet || true +} + +# --- Main Logic --- +if [ "$#" -eq 0 ]; then + usage +fi + +while [[ "$#" -gt 0 ]]; do + case $1 in + --revoke-gke-node-permissions) revoke_gke_node_permissions ;; + --delete-iam-policy-bindings) delete_iam_policy_bindings ;; + --delete-snapshot-bucket) delete_snapshot_bucket ;; + --delete-gvisor-node-pool) delete_gvisor_node_pool ;; + --delete-cluster) delete_cluster ;; + --all) + revoke_gke_node_permissions + delete_iam_policy_bindings + delete_snapshot_bucket + delete_gvisor_node_pool + delete_cluster + ;; + *) usage ;; + esac + shift +done diff --git a/hack/third_party/kubernetes/verify-generated.sh b/hack/third_party/kubernetes/verify-generated.sh new file mode 100755 index 000000000..2a3eaf9cd --- /dev/null +++ b/hack/third_party/kubernetes/verify-generated.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +if ! git diff HEAD --exit-code &>/dev/null; then + echo + echo "Unexpected dirty working directory:" + git status -s + echo + echo "Please commit or stash these changes to run verification." + exit 1 +fi + +name="$1"; shift +if [[ -z "${name}" ]]; then + echo "Usage: $0 [args...]" >&2 + echo "Example: $0 licenses" >&2 + exit 1 +fi + +# Work in a temporary worktree. +tmpdir="$(mktemp -d -t "verify-generated-${name}.XXXXXX")" +git worktree add -f -q "${tmpdir}" HEAD +trap "git worktree remove -f ${tmpdir:?}; rm -rf ${tmpdir:?}" EXIT +cd "${tmpdir}" + +# Update generated files. +update_cmd="./hack/update/${name}.sh" +verify_cmd="./hack/verify/${name}.sh" +"${update_cmd}" "$@" + +# Test for diffs +diffs=$(git status --porcelain | wc -l) +if [[ ${diffs} -gt 0 ]]; then + echo "${verify_cmd} resulted in a diff:" >&2 + git status >&2 + git diff >&2 + echo + echo "Run ${update_cmd} to update generated files." >&2 + exit 1 +fi diff --git a/hack/tools/code-generator/go.mod b/hack/tools/code-generator/go.mod new file mode 100644 index 000000000..f41aa538c --- /dev/null +++ b/hack/tools/code-generator/go.mod @@ -0,0 +1,21 @@ +module github.com/agent-substrate/substrate/hack/tools/code-generator + +go 1.26.1 + +require ( + github.com/go-logr/logr v1.4.3 // indirect + github.com/spf13/pflag v1.0.9 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/text v0.31.0 // indirect + golang.org/x/tools v0.38.0 // indirect + k8s.io/code-generator v0.35.0 // indirect + k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect + k8s.io/klog/v2 v2.130.1 // indirect +) + +tool ( + k8s.io/code-generator/cmd/client-gen + k8s.io/code-generator/cmd/informer-gen + k8s.io/code-generator/cmd/lister-gen +) diff --git a/hack/tools/code-generator/go.sum b/hack/tools/code-generator/go.sum new file mode 100644 index 000000000..1979b5d1b --- /dev/null +++ b/hack/tools/code-generator/go.sum @@ -0,0 +1,20 @@ +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +k8s.io/code-generator v0.35.0 h1:TvrtfKYZTm9oDF2z+veFKSCcgZE3Igv0svY+ehCmjHQ= +k8s.io/code-generator v0.35.0/go.mod h1:iS1gvVf3c/T71N5DOGYO+Gt3PdJ6B9LYSvIyQ4FHzgc= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= diff --git a/hack/tools/controller-gen/go.mod b/hack/tools/controller-gen/go.mod new file mode 100644 index 000000000..2ac53ac1c --- /dev/null +++ b/hack/tools/controller-gen/go.mod @@ -0,0 +1,52 @@ +module github.com/agent-substrate/substrate/hack/tools/controller-gen + +go 1.26.1 + +require ( + github.com/fatih/color v1.18.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/gobuffalo/flect v1.0.3 // indirect + github.com/google/gnostic-models v0.7.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/spf13/cobra v1.10.2 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/mod v0.31.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect + golang.org/x/tools v0.40.0 // indirect + google.golang.org/protobuf v1.36.8 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.35.0 // indirect + k8s.io/apiextensions-apiserver v0.35.0 // indirect + k8s.io/apimachinery v0.35.0 // indirect + k8s.io/code-generator v0.35.0 // indirect + k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + sigs.k8s.io/controller-tools v0.20.1 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect +) + +tool sigs.k8s.io/controller-tools/cmd/controller-gen diff --git a/hack/tools/controller-gen/go.sum b/hack/tools/controller-gen/go.sum new file mode 100644 index 000000000..6b85c0d00 --- /dev/null +++ b/hack/tools/controller-gen/go.sum @@ -0,0 +1,225 @@ +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +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/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= +github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= +github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= +github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +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= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= +github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= +google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY= +k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA= +k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4= +k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU= +k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8= +k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apiserver v0.35.0 h1:CUGo5o+7hW9GcAEF3x3usT3fX4f9r8xmgQeCBDaOgX4= +k8s.io/apiserver v0.35.0/go.mod h1:QUy1U4+PrzbJaM3XGu2tQ7U9A4udRRo5cyxkFX0GEds= +k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE= +k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o= +k8s.io/code-generator v0.35.0 h1:TvrtfKYZTm9oDF2z+veFKSCcgZE3Igv0svY+ehCmjHQ= +k8s.io/code-generator v0.35.0/go.mod h1:iS1gvVf3c/T71N5DOGYO+Gt3PdJ6B9LYSvIyQ4FHzgc= +k8s.io/component-base v0.35.0 h1:+yBrOhzri2S1BVqyVSvcM3PtPyx5GUxCK2tinZz1G94= +k8s.io/component-base v0.35.0/go.mod h1:85SCX4UCa6SCFt6p3IKAPej7jSnF3L8EbfSyMZayJR0= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-tools v0.20.1 h1:gkfMt9YodI0K85oT8rVi80NTXO/kDmabKR5Ajn5GYxs= +sigs.k8s.io/controller-tools v0.20.1/go.mod h1:b4qPmjGU3iZwqn34alUU5tILhNa9+VXK+J3QV0fT/uU= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/tools/go-licenses/go.mod b/hack/tools/go-licenses/go.mod new file mode 100644 index 000000000..b199c61d1 --- /dev/null +++ b/hack/tools/go-licenses/go.mod @@ -0,0 +1,26 @@ +module github.com/agent-substrate/substrate/hack/tools/go-licenses + +go 1.26.1 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.2.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/go-licenses/v2 v2.0.1 // indirect + github.com/google/licenseclassifier/v2 v2.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/otiai10/copy v1.10.0 // indirect + github.com/sergi/go-diff v1.2.0 // indirect + github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect + k8s.io/klog/v2 v2.90.1 // indirect +) + +tool github.com/google/go-licenses/v2 diff --git a/hack/tools/go-licenses/go.sum b/hack/tools/go-licenses/go.sum new file mode 100644 index 000000000..4954fe7d1 --- /dev/null +++ b/hack/tools/go-licenses/go.sum @@ -0,0 +1,147 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-licenses/v2 v2.0.1 h1:ti+9bi5o7DKbeeg5eBb/uZTgsaPNoJaLCh93cRcXsW8= +github.com/google/go-licenses/v2 v2.0.1/go.mod h1:efibo0EDNGkau6AIMOViGW+rTNPudhxX9rCxtfw5zKE= +github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk= +github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg= +github.com/google/licenseclassifier/v2 v2.0.0 h1:1Y57HHILNf4m0ABuMVb6xk4vAJYEUO0gDxNpog0pyeA= +github.com/google/licenseclassifier/v2 v2.0.0/go.mod h1:cOjbdH0kyC9R22sdQbYsFkto4NGCAc+ZSwbeThazEtM= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +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/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ= +github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= +github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= diff --git a/hack/tools/ko/go.mod b/hack/tools/ko/go.mod new file mode 100644 index 000000000..8f2233768 --- /dev/null +++ b/hack/tools/ko/go.mod @@ -0,0 +1,163 @@ +module github.com/agent-substrate/substrate/hack/tools/ko + +go 1.26.3 + +require ( + al.essio.dev/pkg/shellescape v1.6.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.30 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.24 // indirect + github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.7 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.1 // indirect + github.com/Azure/go-autorest/logger v0.2.2 // indirect + github.com/Azure/go-autorest/tracing v0.6.1 // indirect + github.com/BurntSushi/toml v1.6.0 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.12 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.12 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.56.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect + github.com/aws/smithy-go v1.24.2 // indirect + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0 // indirect + github.com/blang/semver v3.5.1+incompatible // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect + github.com/coreos/go-oidc/v3 v3.17.0 // indirect + github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect + github.com/digitorus/pkcs7 v0.0.0-20250730155240-ffadbf3f398c // indirect + github.com/digitorus/timestamp v0.0.0-20250524132541-c45532741eea // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/cli v29.4.0+incompatible // indirect + github.com/docker/docker-credential-helpers v0.9.5 // indirect + github.com/docker/go-connections v0.7.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dprotaso/go-yit v0.0.0-20260209000607-dfb86291624d // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/analysis v0.24.3 // indirect + github.com/go-openapi/errors v0.22.7 // indirect + github.com/go-openapi/jsonpointer v0.22.5 // indirect + github.com/go-openapi/jsonreference v0.21.5 // indirect + github.com/go-openapi/loads v0.23.3 // indirect + github.com/go-openapi/runtime v0.29.3 // indirect + github.com/go-openapi/spec v0.22.4 // indirect + github.com/go-openapi/strfmt v0.26.1 // indirect + github.com/go-openapi/swag v0.25.5 // indirect + github.com/go-openapi/swag/cmdutils v0.25.5 // indirect + github.com/go-openapi/swag/conv v0.25.5 // indirect + github.com/go-openapi/swag/fileutils v0.25.5 // indirect + github.com/go-openapi/swag/jsonname v0.25.5 // indirect + github.com/go-openapi/swag/jsonutils v0.25.5 // indirect + github.com/go-openapi/swag/loading v0.25.5 // indirect + github.com/go-openapi/swag/mangling v0.25.5 // indirect + github.com/go-openapi/swag/netutils v0.25.5 // indirect + github.com/go-openapi/swag/stringutils v0.25.5 // indirect + github.com/go-openapi/swag/typeutils v0.25.5 // indirect + github.com/go-openapi/swag/yamlutils v0.25.5 // indirect + github.com/go-openapi/validate v0.25.2 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect + github.com/google/certificate-transparency-go v1.3.3 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/go-containerregistry v0.21.5 // indirect + github.com/google/ko v0.18.2-0.20260514011618-843e4adc5718 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect + github.com/in-toto/attestation v1.1.2 // indirect + github.com/in-toto/in-toto-golang v0.11.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jedisct1/go-minisign v0.0.0-20241212093149-d2f9f49435c7 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/moby/api v1.54.2 // indirect + github.com/moby/moby/client v0.4.1 // indirect + github.com/moby/term v0.5.2 // indirect + github.com/oklog/ulid/v2 v2.1.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sassoftware/relic v7.2.1+incompatible // indirect + github.com/secure-systems-lab/go-securesystemslib v0.10.0 // indirect + github.com/shibumi/go-pathspec v1.3.0 // indirect + github.com/sigstore/cosign/v3 v3.0.6 // indirect + github.com/sigstore/protobuf-specs v0.5.0 // indirect + github.com/sigstore/rekor v1.5.1 // indirect + github.com/sigstore/rekor-tiles/v2 v2.2.1 // indirect + github.com/sigstore/sigstore v1.10.5 // indirect + github.com/sigstore/sigstore-go v1.1.4 // indirect + github.com/sigstore/timestamp-authority/v2 v2.0.6 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/cobra v1.10.2 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/spf13/viper v1.21.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/theupdateframework/go-tuf v0.7.0 // indirect + github.com/theupdateframework/go-tuf/v2 v2.4.1 // indirect + github.com/transparency-dev/formats v0.1.0 // indirect + github.com/transparency-dev/merkle v0.0.2 // indirect + github.com/vbatts/tar-split v0.12.2 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect + go.opentelemetry.io/otel v1.42.0 // indirect + go.opentelemetry.io/otel/metric v1.42.0 // indirect + go.opentelemetry.io/otel/trace v1.42.0 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + go.yaml.in/yaml/v4 v4.0.0-rc.4 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/mod v0.36.0 // indirect + golang.org/x/net v0.54.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect + golang.org/x/tools v0.45.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260316180232-0b37fe3546d5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 // indirect + google.golang.org/grpc v1.80.0 // indirect + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect + k8s.io/apimachinery v0.36.1 // indirect + k8s.io/klog/v2 v2.140.0 // indirect + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect + sigs.k8s.io/kind v0.31.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect +) + +tool github.com/google/ko diff --git a/hack/tools/ko/go.sum b/hack/tools/ko/go.sum new file mode 100644 index 000000000..a975b5d7d --- /dev/null +++ b/hack/tools/ko/go.sum @@ -0,0 +1,595 @@ +al.essio.dev/pkg/shellescape v1.6.0 h1:NxFcEqzFSEVCGN2yq7Huv/9hyCEGVa/TncnOOBBeXHA= +al.essio.dev/pkg/shellescape v1.6.0/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= +cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= +cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= +cloud.google.com/go/kms v1.26.0 h1:cK9mN2cf+9V63D3H1f6koxTatWy39aTI/hCjz1I+adU= +cloud.google.com/go/kms v1.26.0/go.mod h1:pHKOdFJm63hxBsiPkYtowZPltu9dW0MWvBa6IA4HM58= +cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7EhfW8= +cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= +filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= +filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg= +github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEBnvU96bKHy6LjRsY4E28= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0 h1:E4MgwLBGeVB5f2MdcIVD3ELVAWpr+WD6MUe1i+tM/PA= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.4.0/go.mod h1:Y2b/1clN4zsAoUd/pgNAQHjLDnTis/6ROkUfyob6psM= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= +github.com/Azure/go-autorest/autorest v0.11.30 h1:iaZ1RGz/ALZtN5eq4Nr1SOFSlf2E4pDI3Tcsl+dZPVE= +github.com/Azure/go-autorest/autorest v0.11.30/go.mod h1:t1kpPIOpIVX7annvothKvb0stsrXa37i7b+xpmBW8Fs= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= +github.com/Azure/go-autorest/autorest/adal v0.9.24 h1:BHZfgGsGwdkHDyZdtQRQk1WeUdW0m2WPAwuHZwUi5i4= +github.com/Azure/go-autorest/autorest/adal v0.9.24/go.mod h1:7T1+g0PYFmACYW5LlG2fcoPiPlFHjClyRGL7dRlP5c8= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 h1:Ov8avRZi2vmrE2JcXw+tu5K/yB41r7xK9GZDiBF7NdM= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.13/go.mod h1:5BAVfWLWXihP47vYrPuBKKf4cS0bXI+KM9Qx6ETDJYo= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.7 h1:Q9R3utmFg9K1B4OYtAZ7ZUUvIUdzQt7G2MN5Hi/d670= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.7/go.mod h1:bVrAueELJ0CKLBpUHDIvD516TwmHmzqwCpvONWRsw3s= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/date v0.3.1 h1:o9Z8Jyt+VJJTCZ/UORishuHOusBwolhjokt9s5k8I4w= +github.com/Azure/go-autorest/autorest/date v0.3.1/go.mod h1:Dz/RDmXlfiFFS/eW+b/xMUSFs1tboPVy6UjgADToWDM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.2 h1:hYqBsEBywrrOSW24kkOCXRcKfKhK76OzLTfF+MYDE2o= +github.com/Azure/go-autorest/logger v0.2.2/go.mod h1:I5fg9K52o+iuydlWfa9T5K6WFos9XYr9dYTFzpqgibw= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/Azure/go-autorest/tracing v0.6.1 h1:YUMSrC/CeD1ZnnXcNYU4a/fzsO35u2Fsful9L/2nyR0= +github.com/Azure/go-autorest/tracing v0.6.1/go.mod h1:/3EgjbsjraOqiicERAeu3m7/z0x1TzjQGAwDrJrXGkc= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= +github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= +github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= +github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k= +github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= +github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= +github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/service/ecr v1.56.0 h1:XxNya31nOtsClGghvQ2VkhIB2S/rggb64x5vkHl4xZQ= +github.com/aws/aws-sdk-go-v2/service/ecr v1.56.0/go.mod h1:T+Tz2Xp1gnvtlgvP7OyRHlr84KtI3fZW5Ax/e+s9b64= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.11 h1:2T9NCuNzzBh6RUrwYZBFl1D9lLJ2r2CCbg7w383DjQE= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.11/go.mod h1:FkD34cqOmnqfAEiNHeqOT50SoXqHEgdDsa8BrMw9t+w= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 h1:2HvVAIq+YqgGotK6EkMf+KIEqTISmTYh5zLpYyeTo1Y= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk= +github.com/aws/aws-sdk-go-v2/service/kms v1.50.3 h1:s/zDSG/a/Su9aX+v0Ld9cimUCdkr5FWPmBV8owaEbZY= +github.com/aws/aws-sdk-go-v2/service/kms v1.50.3/go.mod h1:/iSgiUor15ZuxFGQSTf3lA2FmKxFsQoc2tADOarQBSw= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0 h1:JFWXO6QPihCknDdnL6VaQE57km4ZKheHIGd9YiOGcTo= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0/go.mod h1:046/oLyFlYdAghYQE2yHXi/E//VM5Cf3/dFmA+3CZ0c= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= +github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= +github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= +github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= +github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc= +github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q= +github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= +github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= +github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= +github.com/digitorus/pkcs7 v0.0.0-20250730155240-ffadbf3f398c h1:g349iS+CtAvba7i0Ee9EP1TlTZ9w+UncBY6HSmsFZa0= +github.com/digitorus/pkcs7 v0.0.0-20250730155240-ffadbf3f398c/go.mod h1:mCGGmWkOQvEuLdIRfPIpXViBfpWto4AhwtJlAvo62SQ= +github.com/digitorus/timestamp v0.0.0-20250524132541-c45532741eea h1:ALRwvjsSP53QmnN3Bcj0NpR8SsFLnskny/EIMebAk1c= +github.com/digitorus/timestamp v0.0.0-20250524132541-c45532741eea/go.mod h1:GvWntX9qiTlOud0WkQ6ewFm0LPy5JUR1Xo0Ngbd1w6Y= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= +github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= +github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= +github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= +github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dprotaso/go-yit v0.0.0-20260209000607-dfb86291624d h1:/USl0X37Afc2SyjRG4/eNrbm4CZRfZLdzwTy9YXxowA= +github.com/dprotaso/go-yit v0.0.0-20260209000607-dfb86291624d/go.mod h1:k03zg0AFMepR2TrssNeMUISoI0QcX2N58Sl0qPU6MZs= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/analysis v0.24.3 h1:a1hrvMr8X0Xt69KP5uVTu5jH62DscmDifrLzNglAayk= +github.com/go-openapi/analysis v0.24.3/go.mod h1:Nc+dWJ/FxZbhSow5Yh3ozg5CLJioB+XXT6MdLvJUsUw= +github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA= +github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w= +github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA= +github.com/go-openapi/jsonpointer v0.22.5/go.mod h1:gyUR3sCvGSWchA2sUBJGluYMbe1zazrYWIkWPjjMUY0= +github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= +github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= +github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ= +github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA= +github.com/go-openapi/runtime v0.29.3 h1:h5twGaEqxtQg40ePiYm9vFFH1q06Czd7Ot6ufdK0w/Y= +github.com/go-openapi/runtime v0.29.3/go.mod h1:8A1W0/L5eyNJvKciqZtvIVQvYO66NlB7INMSZ9bw/oI= +github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ= +github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ= +github.com/go-openapi/strfmt v0.26.1 h1:7zGCHji7zSYDC2tCXIusoxYQz/48jAf2q+sF6wXTG+c= +github.com/go-openapi/strfmt v0.26.1/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y= +github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU= +github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA= +github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c= +github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g= +github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k= +github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk= +github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc= +github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo= +github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU= +github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo= +github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5 h1:SX6sE4FrGb4sEnnxbFL/25yZBb5Hcg1inLeErd86Y1U= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5/go.mod h1:/2KvOTrKWjVA5Xli3DZWdMCZDzz3uV/T7bXwrKWPquo= +github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU= +github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g= +github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw= +github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY= +github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU= +github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14= +github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M= +github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII= +github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E= +github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc= +github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ= +github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.1 h1:NZOrZmIb6PTv5LTFxr5/mKV/FjbUzGE7E6gLz7vFoOQ= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.1/go.mod h1:r7dwsujEHawapMsxA69i+XMGZrQ5tRauhLAjV/sxg3Q= +github.com/go-openapi/testify/v2 v2.4.1 h1:zB34HDKj4tHwyUQHrUkpV0Q0iXQ6dUCOQtIqn8hE6Iw= +github.com/go-openapi/testify/v2 v2.4.1/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0= +github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY= +github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA= +github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/certificate-transparency-go v1.3.3 h1:hq/rSxztSkXN2tx/3jQqF6Xc0O565UQPdHrOWvZwybo= +github.com/google/certificate-transparency-go v1.3.3/go.mod h1:iR17ZgSaXRzSa5qvjFl8TnVD5h8ky2JMVio+dzoKMgA= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= +github.com/google/go-containerregistry v0.21.5/go.mod h1:ySvMuiWg+dOsRW0Hw8GYwfMwBlNRTmpYBFJPlkco5zU= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/ko v0.18.2-0.20260514011618-843e4adc5718 h1:u6qHnPQOwwvm+Rh0OtAhP8pALevMPL9EeXNJjELCJWE= +github.com/google/ko v0.18.2-0.20260514011618-843e4adc5718/go.mod h1:4pU7vdsogGSse67nU22D+aVzfJ4OfxKKoJW8+AdagCs= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/trillian v1.7.2 h1:EPBxc4YWY4Ak8tcuhyFleY+zYlbCDCa4Sn24e1Ka8Js= +github.com/google/trillian v1.7.2/go.mod h1:mfQJW4qRH6/ilABtPYNBerVJAJ/upxHLX81zxNQw05s= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= +github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.19.0 h1:fYQaUOiGwll0cGj7jmHT/0nPlcrZDFPrZRhTsoCr8hE= +github.com/googleapis/gax-go/v2 v2.19.0/go.mod h1:w2ROXVdfGEVFXzmlciUU4EdjHgWvB5h2n6x/8XSTTJA= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/vault/api v1.22.0 h1:+HYFquE35/B74fHoIeXlZIP2YADVboaPjaSicHEZiH0= +github.com/hashicorp/vault/api v1.22.0/go.mod h1:IUZA2cDvr4Ok3+NtK2Oq/r+lJeXkeCrHRmqdyWfpmGM= +github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= +github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= +github.com/in-toto/attestation v1.1.2 h1:MBFn6lsMq6dptQZJBhalXTcWMb/aJy3V+GX3VYj/V1E= +github.com/in-toto/attestation v1.1.2/go.mod h1:gYFddHMZj3DiQ0b62ltNi1Vj5rC879bTmBbrv9CRHpM= +github.com/in-toto/in-toto-golang v0.11.0 h1:nfidMYBFx+E0lnmX5KUnN2Pdm8zdNKal1ayjJuzzRoA= +github.com/in-toto/in-toto-golang v0.11.0/go.mod h1:u3PjTnwFKjp5a1YCcw8SJg0G+tMeKfVoWsWeFMDCMtw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo= +github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jedisct1/go-minisign v0.0.0-20241212093149-d2f9f49435c7 h1:FWpSWRD8FbVkKQu8M1DM9jF5oXFLyE+XpisIYfdzbic= +github.com/jedisct1/go-minisign v0.0.0-20241212093149-d2f9f49435c7/go.mod h1:BMxO138bOokdgt4UaxZiEfypcSHX0t6SIFimVP1oRfk= +github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY= +github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY= +github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/letsencrypt/boulder v0.20260223.0 h1:xdS2OnJNUasR6TgVIOpqqcvdkOu47+PQQMBk9ThuWBw= +github.com/letsencrypt/boulder v0.20260223.0/go.mod h1:r3aTSA7UZ7dbDfiGK+HLHJz0bWNbHk6YSPiXgzl23sA= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg= +github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY= +github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= +github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= +github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= +github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= +github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A= +github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= +github.com/sassoftware/relic/v7 v7.6.2 h1:rS44Lbv9G9eXsukknS4mSjIAuuX+lMq/FnStgmZlUv4= +github.com/sassoftware/relic/v7 v7.6.2/go.mod h1:kjmP0IBVkJZ6gXeAu35/KCEfca//+PKM6vTAsyDPY+k= +github.com/secure-systems-lab/go-securesystemslib v0.10.0 h1:l+H5ErcW0PAehBNrBxoGv1jjNpGYdZ9RcheFkB2WI14= +github.com/secure-systems-lab/go-securesystemslib v0.10.0/go.mod h1:MRKONWmRoFzPNQ9USRF9i1mc7MvAVvF1LlW8X5VWDvk= +github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= +github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= +github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= +github.com/sigstore/cosign/v3 v3.0.6 h1:k8XaUd9pmLknHBst/v0rUGHVdB4D9cfaBmWUaMAOocE= +github.com/sigstore/cosign/v3 v3.0.6/go.mod h1:ckLRkVecfUCYxL8isHODY9lwyKmDaRCPn00p6yFxHg0= +github.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY= +github.com/sigstore/protobuf-specs v0.5.0/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc= +github.com/sigstore/rekor v1.5.1 h1:Ca1egHRWRuDvXV4tZu9aXEXc3Gej9FG+HKeapV9OAMQ= +github.com/sigstore/rekor v1.5.1/go.mod h1:gTLDuZuo3SyQCuZvKqwRPA79Qo/2rw39/WtLP/rZjUQ= +github.com/sigstore/rekor-tiles/v2 v2.2.1 h1:UmV1CBQ3SjxxPGpFmwDoOhoIwiKpM2Qm1pU5tPGmvNk= +github.com/sigstore/rekor-tiles/v2 v2.2.1/go.mod h1:z8n6l6oidpaLjjE6rJERuQqY9X38ulnHZCXyL+DEL7U= +github.com/sigstore/sigstore v1.10.5 h1:KqrOjDhNOVY+uOzQFat2FrGLClPPCb3uz8pK3wuI+ow= +github.com/sigstore/sigstore v1.10.5/go.mod h1:k/mcVVXw3I87dYG/iCVTSW2xTrW7vPzxxGic4KqsqXs= +github.com/sigstore/sigstore-go v1.1.4 h1:wTTsgCHOfqiEzVyBYA6mDczGtBkN7cM8mPpjJj5QvMg= +github.com/sigstore/sigstore-go v1.1.4/go.mod h1:2U/mQOT9cjjxrtIUeKDVhL+sHBKsnWddn8URlswdBsg= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.5 h1:aqHRubTITULckG9JAcq2FEhtKkT/RRE8oErfuV3smSI= +github.com/sigstore/sigstore/pkg/signature/kms/aws v1.10.5/go.mod h1:h9eK9QyPqpFskF/ewFkRLtwh4/Q3FLc2/DXbym4IHN8= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.5 h1:+9C6CUkv+J4iT67Lx+H1EGBfAdoAHqXumHadeIj9jA4= +github.com/sigstore/sigstore/pkg/signature/kms/azure v1.10.5/go.mod h1:myZsg7wRiy/vf102g5uUAitYhtXCwepmAGxgHG1VHuE= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.5 h1:BpQx6AhjwIN9LmlO4ypkcMcHiWiepgZQGSw5U69frHU= +github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.10.5/go.mod h1:ejMD/17lMJ4HykQRPdj5NNr+OQYIEZto8HjDKghVMOA= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.5 h1:OFwQZgWkB/6J6W5sy3SkXE4pJnhNRnE2cJd8ySXmHpo= +github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.10.5/go.mod h1:Ee/enmyxi/RFLVlajbnjgH2wOWQwlJ0wY8qZrk43hEw= +github.com/sigstore/timestamp-authority/v2 v2.0.6 h1:1Vh7/SdmLsVLG6Br6/bisd1SnlicfDm0MJYiA+D7Ppw= +github.com/sigstore/timestamp-authority/v2 v2.0.6/go.mod h1:Nk5ucGBDyH0tXAIMZ0prf6xn8qfTnbJhSq+CDabYcfc= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= +github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug= +github.com/theupdateframework/go-tuf/v2 v2.4.1 h1:K6ewW064rKZCPkRo1W/CTbTtm/+IB4+coG1iNURAGCw= +github.com/theupdateframework/go-tuf/v2 v2.4.1/go.mod h1:Nex2enPVYDFCklrnbTzl3OVwD7fgIAj0J5++z/rvCj8= +github.com/tink-crypto/tink-go-awskms/v2 v2.1.0 h1:N9UxlsOzu5mttdjhxkDLbzwtEecuXmlxZVo/ds7JKJI= +github.com/tink-crypto/tink-go-awskms/v2 v2.1.0/go.mod h1:PxSp9GlOkKL9rlybW804uspnHuO9nbD98V/fDX4uSis= +github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0 h1:3B9i6XBXNTRspfkTC0asN5W0K6GhOSgcujNiECNRNb0= +github.com/tink-crypto/tink-go-gcpkms/v2 v2.2.0/go.mod h1:jY5YN2BqD/KSCHM9SqZPIpJNG/u3zwfLXHgws4x2IRw= +github.com/tink-crypto/tink-go-hcvault/v2 v2.4.0 h1:j+S+WKBQ5ya26A5EM/uXoVe+a2IaPQN8KgBJZ22cJ+4= +github.com/tink-crypto/tink-go-hcvault/v2 v2.4.0/go.mod h1:OCKJIujnTzDq7f+73NhVs99oA2c1TR6nsOpuasYM6Yo= +github.com/tink-crypto/tink-go/v2 v2.6.0 h1:+KHNBHhWH33Vn+igZWcsgdEPUxKwBMEe0QC60t388v4= +github.com/tink-crypto/tink-go/v2 v2.6.0/go.mod h1:2WbBA6pfNsAfBwDCggboaHeB2X29wkU8XHtGwh2YIk8= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= +github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= +github.com/transparency-dev/formats v0.1.0 h1:oL0zUFuYUjg8AbtjPMnIRDmjbaHo5jCjEWU5yaNuz0g= +github.com/transparency-dev/formats v0.1.0/go.mod h1:d2FibUOHfCMdCe/+/rbKt1IPLBbPTDfwj46kt541/mU= +github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4= +github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A= +github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= +github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= +github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ= +github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns= +github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ= +github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18= +github.com/ysmood/got v0.40.0 h1:ZQk1B55zIvS7zflRrkGfPDrPG3d7+JOza1ZkNxcc74Q= +github.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg= +github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= +github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU= +github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= +github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 h1:RN3ifU8y4prNWeEnQp2kRRHz8UwonAEYZl8tUzHEXAk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0/go.mod h1:habDz3tEWiFANTo6oUE99EmaFUrCNYAAg3wiVmusm70= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg= +go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho= +go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc= +go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4= +go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI= +go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo= +go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= +go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA= +go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc= +go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY= +go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc= +go.step.sm/crypto v0.77.2 h1:qFjjei+RHc5kP5R7NW9OUWT7SqWIuAOvOkXqg4fNWj8= +go.step.sm/crypto v0.77.2/go.mod h1:W0YJb9onM5l78qgkXIJ2Up6grnwW8EtpCKIza/NCg0o= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U= +go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= +golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.272.0 h1:eLUQZGnAS3OHn31URRf9sAmRk3w2JjMx37d2k8AjJmA= +google.golang.org/api v0.272.0/go.mod h1:wKjowi5LNJc5qarNvDCvNQBn3rVK8nSy6jg2SwRwzIA= +google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE= +google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw= +google.golang.org/genproto/googleapis/api v0.0.0-20260316180232-0b37fe3546d5 h1:CogIeEXn4qWYzzQU0QqvYBM8yDF9cFYzDq9ojSpv0Js= +google.golang.org/genproto/googleapis/api v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:EIQZ5bFCfRQDV4MhRle7+OgjNtZ6P1PiZBgAKuxXu/Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 h1:aJmi6DVGGIStN9Mobk/tZOOQUBbj0BPjZjjnOdoZKts= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +k8s.io/apimachinery v0.36.1 h1:G63Gjx2W+q0YD+72Vo8oY0nDnePVwnuzTmmy5ENrVSA= +k8s.io/apimachinery v0.36.1/go.mod h1:ibYOR00vW/I1kzvi5SF0dRuJ52BvKtfvRdOn35GPQ+8= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +sigs.k8s.io/kind v0.31.0 h1:UcT4nzm+YM7YEbqiAKECk+b6dsvc/HRZZu9U0FolL1g= +sigs.k8s.io/kind v0.31.0/go.mod h1:FSqriGaoTPruiXWfRnUXNykF8r2t+fHtK0P0m1AbGF8= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= +software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= +software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= diff --git a/hack/tools/protoc-gen-go-grpc/go.mod b/hack/tools/protoc-gen-go-grpc/go.mod new file mode 100644 index 000000000..57061ae10 --- /dev/null +++ b/hack/tools/protoc-gen-go-grpc/go.mod @@ -0,0 +1,10 @@ +module github.com/agent-substrate/substrate/hack/tools/protoc-gen-go-grpc + +go 1.26.1 + +require ( + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.1 // indirect + google.golang.org/protobuf v1.36.11 // indirect +) + +tool google.golang.org/grpc/cmd/protoc-gen-go-grpc diff --git a/hack/tools/protoc-gen-go-grpc/go.sum b/hack/tools/protoc-gen-go-grpc/go.sum new file mode 100644 index 000000000..d860c358a --- /dev/null +++ b/hack/tools/protoc-gen-go-grpc/go.sum @@ -0,0 +1,16 @@ +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.1 h1:/WILD1UcXj/ujCxgoL/DvRgt2CP3txG8+FwkUbb9110= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.1/go.mod h1:YNKnb2OAApgYn2oYY47Rn7alMr1zWjb2U8Q0aoGWiNc= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/hack/tools/protoc-gen-go/go.mod b/hack/tools/protoc-gen-go/go.mod new file mode 100644 index 000000000..24e6568ae --- /dev/null +++ b/hack/tools/protoc-gen-go/go.mod @@ -0,0 +1,7 @@ +module github.com/agent-substrate/substrate/hack/tools/protoc-gen-go + +go 1.26.1 + +require google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect + +tool google.golang.org/protobuf/cmd/protoc-gen-go diff --git a/hack/tools/protoc-gen-go/go.sum b/hack/tools/protoc-gen-go/go.sum new file mode 100644 index 000000000..773f9f83e --- /dev/null +++ b/hack/tools/protoc-gen-go/go.sum @@ -0,0 +1,4 @@ +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/hack/tools/setup-envtest/go.mod b/hack/tools/setup-envtest/go.mod new file mode 100644 index 000000000..1ffc7ca1b --- /dev/null +++ b/hack/tools/setup-envtest/go.mod @@ -0,0 +1,18 @@ +module github.com/agent-substrate/substrate/hack/tools/setup-envtest + +go 1.26.1 + +require ( + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/pflag v1.0.9 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + golang.org/x/text v0.33.0 // indirect + sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20260405152528-6210f847b2c1 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect +) + +tool sigs.k8s.io/controller-runtime/tools/setup-envtest diff --git a/hack/tools/setup-envtest/go.sum b/hack/tools/setup-envtest/go.sum new file mode 100644 index 000000000..39bc91585 --- /dev/null +++ b/hack/tools/setup-envtest/go.sum @@ -0,0 +1,60 @@ +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y= +github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= +github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/apimachinery v0.36.0-beta.0 h1:FioYxKfnvZuo0EUX/W9X0FhH3omaG7dEdtDk2IsfEtU= +k8s.io/apimachinery v0.36.0-beta.0/go.mod h1:AEUkaeqhot34WXPkRiWxszI4nUd8m40AAYi28N33hqc= +sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20260405152528-6210f847b2c1 h1:E0yXEDHo7QliVHw0/gsbBq5m2VmRUDry81sJgj6cT28= +sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20260405152528-6210f847b2c1/go.mod h1:K1AkL5uTv9m0NMzQ+ULndYovO4u9vwO/voMwXt09cOg= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/update-all.sh b/hack/update-all.sh new file mode 100755 index 000000000..99d6bc449 --- /dev/null +++ b/hack/update-all.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +cd "${ROOT}" +for F in $(find ./hack/update -name '*.sh'); do + echo "Running ${F}" + "${F}" "$@" +done diff --git a/hack/update/README.md b/hack/update/README.md new file mode 100644 index 000000000..dd48ea69c --- /dev/null +++ b/hack/update/README.md @@ -0,0 +1,7 @@ +# Update scripts + +This directory holds simple scripts which update the current tree in some way +(e.g. generated code). + +Every script in this directory should have a corresponding entry in +`../update`. diff --git a/hack/update/go-mod-tidy.sh b/hack/update/go-mod-tidy.sh new file mode 100755 index 000000000..c5691b4e1 --- /dev/null +++ b/hack/update/go-mod-tidy.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +cd "${ROOT}" +go mod tidy + +# Tidy all isolated tool modules under hack/tools/ +for D in "${ROOT}/hack/tools"/*; do + if [ -d "${D}" ] && [ -f "${D}/go.mod" ]; then + (cd "${D}" && go mod tidy) + fi +done diff --git a/hack/update/gofmt.sh b/hack/update/gofmt.sh new file mode 100755 index 000000000..dca222048 --- /dev/null +++ b/hack/update/gofmt.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +# Find all top-level directories containing Go files, and run gofmt on them. +dirs=( + $(git ls-files -cmo --exclude-standard ':(glob)**/*.go' \ + `# Omit LICENSES/, which can contain bundled source code. ` \ + | grep -v '^LICENSES' \ + | cut -f1 -d/ \ + | uniq) +) + +for dir in ${dirs[@]}; do + gofmt -s -w ${dir} +done diff --git a/hack/update/licenses.sh b/hack/update/licenses.sh new file mode 100755 index 000000000..a1007b8d2 --- /dev/null +++ b/hack/update/licenses.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" +OUTDIR="LICENSES" # under $ROOT + +cd "${ROOT}" + +# Ensure the tool is built and up-to-date +GO_LICENSES_BIN="$(bash "${ROOT}/hack/run-tool.sh" --print-bin-path go-licenses)" + +# Clean out previous licenses +rm -rf "${OUTDIR}" +mkdir -p "${OUTDIR}" + +# TODO: determine full release target set and dedupe ... +targets=( + "linux/amd64" + "linux/arm64" + "darwin/amd64" + "darwin/arm64" +) + +tmpfile="$(mktemp -t "update-licenses.XXXXXX")" +trap "rm -f ${tmpfile}" EXIT + +for target in "${targets[@]}"; do + IFS="/" read -r target_os target_arch <<< "${target}" + + # Create a temporary output folder for each target + tmp_out="$(mktemp -d -t "update-licenses-out.XXXXXX")" + + GOOS="${target_os}" \ + GOARCH="${target_arch}" \ + CGO_ENABLED=1 \ + "${GO_LICENSES_BIN}" save ./... --force --save_path="${tmp_out}" > "${tmpfile}" 2>&1 || { + echo "Failed for ${target_os}/${target_arch}:" >&2 + cat "${tmpfile}" + rm -rf "${tmp_out}" + exit 1 + } + + # Bug in go-licenses? Our repo gets included in a loop + rm -rf "${tmp_out}/github.com/agent-substrate/substrate" + + # Merge the results into the main OUTDIR + if [ "$(ls -A "${tmp_out}")" ]; then + chmod -R u+w "${OUTDIR}" 2>/dev/null || true + cp -R "${tmp_out}/." "${OUTDIR}/" + fi + rm -rf "${tmp_out}" +done + +# Clean up empty directories +find "${OUTDIR}" -type d -empty -delete diff --git a/hack/util/verify-boilerplate.py b/hack/util/verify-boilerplate.py new file mode 100755 index 000000000..752555561 --- /dev/null +++ b/hack/util/verify-boilerplate.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys +import subprocess + +import datetime +import re + +current_year = datetime.date.today().year + +def match_copyright(line): + match = re.search(r"Copyright\s+(\d{4})\s+Google LLC", line) + if not match: + return False + year = int(match.group(1)) + return 2026 <= year <= current_year + +ASLV2_HEADER = [ + "Licensed under the Apache License, Version 2.0 (the \"License\");", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "http://www.apache.org/licenses/LICENSE-2.0", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an \"AS IS\" BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." +] + + +def clean_line(line): + """Removes leading comment markers and whitespace.""" + line = line.strip() + if line.startswith('//'): + line = line[2:] + elif line.startswith('#'): + line = line[1:] + return line.strip() + +def verify_file(filepath): + try: + with open(filepath, 'r', encoding='utf-8') as f: + lines = f.readlines() + except Exception as e: + print(f"Error reading {filepath}: {e}") + return False + + # Clean the lines to extract text + cleaned_lines = [clean_line(line) for line in lines[:30]] + cleaned_lines = [line for line in cleaned_lines if line] # remove empty lines + + # We just check if the keywords appear in order + # to be resilient to variations in whitespace or layout + found_copyright = False + header_idx = 0 + for line in cleaned_lines: + if not found_copyright: + if match_copyright(line): + found_copyright = True + continue + + if header_idx < len(ASLV2_HEADER): + target = ASLV2_HEADER[header_idx].strip() + if target in line: + header_idx += 1 + + if not found_copyright or header_idx < len(ASLV2_HEADER): + print(f"Missing License Header: {filepath}") + return False + + return True + + + return True + +def main(): + # Get tracked files via git ls-files + try: + output = subprocess.check_output(['git', 'ls-files', '--others', '--cached', '--exclude-standard'], text=True) + except subprocess.CalledProcessError as e: + print(f"Error running git ls-files: {e}") + sys.exit(1) + + files = output.splitlines() + failed_files = [] + + for filepath in files: + _, ext = os.path.splitext(filepath) + filename = os.path.basename(filepath) + + # Skip non-source-code files + if ext in ['.md', '.txt', '.png', '.jpg', '.jpeg', '.gif', '.mp4', '.json', '.pdf', '.ico', '.woff', '.woff2', '.ttf', '.otf']: + continue + if filename in ['LICENSE', 'NOTICE', '.gitignore', 'go.mod', 'go.sum']: + continue + + # exclude third_party files, which should have their OWN LICENSE + # TODO: verify LICENSE exists in each third_party directory? + if "third_party" in filepath: + continue + + # exclude top-level LICENSES directory + if filepath.startswith("LICENSES/"): + continue + + # exclude github config + if filepath in [".github/dependabot.yml"]: + continue + + if not verify_file(filepath): + failed_files.append(filepath) + + if failed_files: + print(f"\nVerification failed. {len(failed_files)} file(s) missing license headers.") + sys.exit(1) + + sys.exit(0) + +if __name__ == '__main__': + main() diff --git a/hack/verify-all.sh b/hack/verify-all.sh new file mode 100755 index 000000000..64dcb627a --- /dev/null +++ b/hack/verify-all.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +cd "${ROOT}" +for F in $(find ./hack/verify -name '*.sh'); do + echo "Running ${F}" + "${F}" "$@" +done diff --git a/hack/verify/README.md b/hack/verify/README.md new file mode 100644 index 000000000..fa79ce5bf --- /dev/null +++ b/hack/verify/README.md @@ -0,0 +1,7 @@ +# Verify scripts + +This directory holds simple scripts which verify the current tree in some way +(e.g. generated code). + +Most of the scripts in this directory should have a corresponding entry in +`../verify`. diff --git a/hack/verify/boilerplate.sh b/hack/verify/boilerplate.sh new file mode 100755 index 000000000..e575d8159 --- /dev/null +++ b/hack/verify/boilerplate.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +cd "${ROOT}" +hack/util/verify-boilerplate.py diff --git a/hack/verify/go-mod-tidy.sh b/hack/verify/go-mod-tidy.sh new file mode 100755 index 000000000..5d6a9ef81 --- /dev/null +++ b/hack/verify/go-mod-tidy.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +cd "${ROOT}" +./hack/third_party/kubernetes/verify-generated.sh go-mod-tidy "$@" diff --git a/hack/verify/gofmt.sh b/hack/verify/gofmt.sh new file mode 100755 index 000000000..70357fc2a --- /dev/null +++ b/hack/verify/gofmt.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" +cd "${ROOT}" + +./hack/third_party/kubernetes/verify-generated.sh gofmt "$@" diff --git a/hack/verify/licenses.sh b/hack/verify/licenses.sh new file mode 100755 index 000000000..3ce13a697 --- /dev/null +++ b/hack/verify/licenses.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +ROOT="$(git rev-parse --show-toplevel)" + +cd "${ROOT}" +./hack/third_party/kubernetes/verify-generated.sh licenses "$@" diff --git a/internal/ategcs/ategcs.go b/internal/ategcs/ategcs.go new file mode 100644 index 000000000..9290b8daf --- /dev/null +++ b/internal/ategcs/ategcs.go @@ -0,0 +1,279 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ategcs + +import ( + "context" + "fmt" + "io" + "log/slog" + "net/url" + "os" + "path/filepath" + "strings" + + "cloud.google.com/go/storage" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/klauspost/compress/zstd" + "go.opentelemetry.io/otel" +) + +type ObjectStorage interface { + GetObject(ctx context.Context, bucket, object string) (io.ReadCloser, error) + PutObject(ctx context.Context, bucket, object string, reader io.Reader) error +} + +type gcsClient struct { + client *storage.Client +} + +func NewGCSClient(client *storage.Client) ObjectStorage { + return &gcsClient{client: client} +} + +func (g *gcsClient) GetObject(ctx context.Context, bucket, object string) (io.ReadCloser, error) { + return g.client.Bucket(bucket).Object(object).NewReader(ctx) +} + +func (g *gcsClient) PutObject(ctx context.Context, bucket, object string, reader io.Reader) error { + wc := g.client.Bucket(bucket).Object(object).NewWriter(ctx) + defer wc.Close() + _, err := io.Copy(wc, reader) + return err +} + +type s3Client struct { + client *s3.Client +} + +func NewS3Client(client *s3.Client) ObjectStorage { + return &s3Client{client: client} +} + +func (s *s3Client) GetObject(ctx context.Context, bucket, object string) (io.ReadCloser, error) { + output, err := s.client.GetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(object), + }) + if err != nil { + return nil, err + } + return output.Body, nil +} + +func (s *s3Client) PutObject(ctx context.Context, bucket, object string, reader io.Reader) error { + // Try creating the bucket first (ignore if it already exists) + _, _ = s.client.CreateBucket(ctx, &s3.CreateBucketInput{ + Bucket: aws.String(bucket), + }) + + _, err := s.client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String(bucket), + Key: aws.String(object), + Body: reader, + }) + return err +} + +func ParseGCSURL(gsURL string) (string, string, error) { + parsed, err := url.Parse(gsURL) + if err != nil { + return "", "", fmt.Errorf("while parsing %q: %w", gsURL, err) + } + + return parsed.Host, strings.TrimPrefix(parsed.Path, "/"), nil +} + +func FetchFromGCS(ctx context.Context, client ObjectStorage, gsURL string) ([]byte, error) { + bucket, object, err := ParseGCSURL(gsURL) + if err != nil { + return nil, fmt.Errorf("while parsing url: %w", err) + } + + rc, err := client.GetObject(ctx, bucket, object) + if err != nil { + return nil, fmt.Errorf("while getting object bucket=%q object=%q: %w", bucket, object, err) + } + defer rc.Close() + + content, err := io.ReadAll(rc) + if err != nil { + return nil, fmt.Errorf("while reading all content: %w", err) + } + + return content, nil +} + +func FetchLocalFileFromGCS(ctx context.Context, client ObjectStorage, gsURL, localPath string, mode os.FileMode) error { + bucket, object, err := ParseGCSURL(gsURL) + if err != nil { + return fmt.Errorf("while parsing url: %w", err) + } + + rc, err := client.GetObject(ctx, bucket, object) + if err != nil { + return fmt.Errorf("while getting object bucket=%q object=%q: %w", bucket, object, err) + } + defer rc.Close() + + localDir := filepath.Dir(localPath) + tmpFile, err := os.CreateTemp(localDir, filepath.Base(localPath)+"-download-") + if err != nil { + return fmt.Errorf("while temp file: %w", err) + } + defer tmpFile.Close() + + _, err = io.Copy(tmpFile, rc) + if err != nil { + return fmt.Errorf("while copying data: %w", err) + } + + if err := tmpFile.Chmod(mode); err != nil { + return fmt.Errorf("while setting file mode: %w", err) + } + + if err := os.Rename(tmpFile.Name(), localPath); err != nil { + return fmt.Errorf("while renaming temp file to target: %w", err) + } + + return nil +} + +func SendToGCSWithZstd(ctx context.Context, client ObjectStorage, gsURL string, content io.Reader) (err error) { + bucket, object, err := ParseGCSURL(gsURL) + if err != nil { + return fmt.Errorf("while parsing URL: %w", err) + } + + // Create a temporary file to store compressed data + tmpFile, err := os.CreateTemp("", "substrate-upload-compress-") + if err != nil { + return fmt.Errorf("while creating temp compress file: %w", err) + } + defer os.Remove(tmpFile.Name()) + defer tmpFile.Close() + + zwc, err := zstd.NewWriter(tmpFile) + if err != nil { + return fmt.Errorf("while creating zstd writer: %w", err) + } + + _, err = io.Copy(zwc, content) + if err != nil { + zwc.Close() + return fmt.Errorf("while compressing data to temp file: %w", err) + } + if err := zwc.Close(); err != nil { + return fmt.Errorf("while closing zstd writer: %w", err) + } + + // Seek back to the beginning of the temp file + if _, err := tmpFile.Seek(0, 0); err != nil { + return fmt.Errorf("while seeking temp file: %w", err) + } + + // Upload the seekable temp file + if err := client.PutObject(ctx, bucket, object, tmpFile); err != nil { + return fmt.Errorf("while putting object: %w", err) + } + return nil +} + +func SendLocalFileToGCSWithZstd(ctx context.Context, client ObjectStorage, gsURL string, localFilePath string) (err error) { + localFile, err := os.Open(localFilePath) + if err != nil { + return fmt.Errorf("while opening %q: %w", localFilePath, err) + } + defer func() { + if closeErr := localFile.Close(); closeErr != nil { + if err == nil { + err = closeErr + } else { + slog.InfoContext(ctx, "Dropped error from closing localFile", slog.String("localFile", localFilePath), slog.Any("err", err)) + } + } + }() + + if err := SendToGCSWithZstd(ctx, client, gsURL, localFile); err != nil { + return fmt.Errorf("in sendToGCSWithZstd: %w", err) + } + + return nil +} + +func fetchFromGCSWithZstd(ctx context.Context, client ObjectStorage, gsURL string, out io.Writer) (err error) { + bucket, object, err := ParseGCSURL(gsURL) + if err != nil { + return fmt.Errorf("while parsing URL: %w", err) + } + + rc, err := client.GetObject(ctx, bucket, object) + if err != nil { + return fmt.Errorf("while getting object: %w", err) + } + defer func() { + if closeErr := rc.Close(); closeErr != nil { + if err != nil { + err = closeErr + } else { + slog.InfoContext(ctx, "Dropped error from rc.Close", slog.Any("err", closeErr)) + } + } + }() + + zrc, err := zstd.NewReader(rc, zstd.WithDecoderConcurrency(1)) + if err != nil { + return fmt.Errorf("in zstd.NewReader: %w", err) + } + defer zrc.Close() + + _, err = io.Copy(out, zrc) + if err != nil { + return fmt.Errorf("in io.Copy: %w", err) + } + + return nil +} + +func FetchLocalFileFromGCSWithZstd(ctx context.Context, client ObjectStorage, gsURL string, localFilePath string) (err error) { + tracer := otel.Tracer("ateom-gvisor") + ctx, span := tracer.Start(ctx, "fetchLocalFileFromGCSWithZstd") + defer span.End() + + localFile, err := os.Create(localFilePath) + if err != nil { + return fmt.Errorf("while opening %q: %w", localFilePath, err) + } + defer func() { + if closeErr := localFile.Close(); closeErr != nil { + if err == nil { + err = closeErr + } else { + slog.InfoContext(ctx, "Dropped error from closing localFile", slog.String("localFile", localFilePath), slog.Any("err", err)) + } + } + }() + + if err := localFile.Chmod(0o600); err != nil { + return fmt.Errorf("in localFile.Chmod(0o600): %w", err) + } + + if err := fetchFromGCSWithZstd(ctx, client, gsURL, localFile); err != nil { + return fmt.Errorf("while fetching %q from GCS: %w", gsURL, err) + } + + return nil +} diff --git a/internal/ateompath/ateompath.go b/internal/ateompath/ateompath.go new file mode 100644 index 000000000..a0a7ba669 --- /dev/null +++ b/internal/ateompath/ateompath.go @@ -0,0 +1,140 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Ateom and atelet need to agree on many filesystem paths. They are defined in this package. +package ateompath + +import ( + "path/filepath" +) + +const ( + // The base path. This is both the path of the root shared folder on the + // host filesystem, and when it is mounted into ateom and atelet containers. + BasePath = "/run/ateom-gvisor" +) + +var ( + // StaticFilesDir holds things like downloaded runsc binaries. + StaticFilesDir = filepath.Join(BasePath, "static-files") +) + +func RunSCBinaryPath(sha256 string) string { + return filepath.Join(StaticFilesDir, "runsc-"+sha256) +} + +func AteomPath(ateomNamespace, ateomName string) string { + return filepath.Join( + BasePath, + "ateoms", + ateomNamespace+":"+ateomName, + ) +} + +func AteomSocketPath(ateomNamespace, ateomName string) string { + return filepath.Join( + AteomPath(ateomNamespace, ateomName), + "ateom.sock", + ) +} + +func AteomNetNSName(ateomNamespace, ateomName string) string { + return "ateom:" + ateomNamespace + ":" + ateomName +} + +func AteomNetNSPath(ateomNamespace, ateomName string) string { + return filepath.Join( + "/run/netns", + AteomNetNSName(ateomNamespace, ateomName), + ) +} + +func ActorPath(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + BasePath, + "actors", + actorTemplateNamespace+":"+actorTemplateName+":"+actorID, + ) +} + +func RunSCStateDir(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + ActorPath(actorTemplateNamespace, actorTemplateName, actorID), + "runsc-state", + ) +} + +func OCIBundleDir(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + ActorPath(actorTemplateNamespace, actorTemplateName, actorID), + "bundles", + ) +} + +func OCIBundlePath(actorTemplateNamespace, actorTemplateName, actorID, containerName string) string { + return filepath.Join( + OCIBundleDir(actorTemplateNamespace, actorTemplateName, actorID), + containerName, + ) +} + +func RunscDebugLogDir(actorTemplateNamespace, actorTemplateName, actorID, containerName string) string { + return filepath.Join( + ActorPath(actorTemplateNamespace, actorTemplateName, actorID), + "runsc-debug-logs", + containerName, + ) +} + +func CheckpointDir(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + ActorPath(actorTemplateNamespace, actorTemplateName, actorID), + "checkpoint", + ) +} + +func CheckpointImgPath(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + CheckpointDir(actorTemplateNamespace, actorTemplateName, actorID), + "checkpoint.img", // gvisor implementation detail, technically. + ) +} + +func PagesImgPath(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + CheckpointDir(actorTemplateNamespace, actorTemplateName, actorID), + "pages.img", // gvisor implementation detail, technically. + ) +} + +func PagesMetaImgPath(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + CheckpointDir(actorTemplateNamespace, actorTemplateName, actorID), + "pages_meta.img", // gvisor implementation detail, technically. + ) +} + +func PIDFileDir(actorTemplateNamespace, actorTemplateName, actorID string) string { + return filepath.Join( + ActorPath(actorTemplateNamespace, actorTemplateName, actorID), + "pidfiles", + ) +} + +func PIDFilePath(actorTemplateNamespace, actorTemplateName, actorID, containerName string) string { + return filepath.Join( + PIDFileDir(actorTemplateNamespace, actorTemplateName, actorID), + containerName+".pid", + ) +} diff --git a/internal/controllers/actortemplate_controller.go b/internal/controllers/actortemplate_controller.go new file mode 100644 index 000000000..a288e2020 --- /dev/null +++ b/internal/controllers/actortemplate_controller.go @@ -0,0 +1,161 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controllers + +import ( + "context" + "fmt" + "time" + + atev1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/proto/ateapipb" + "github.com/google/uuid" + k8errors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + GoldenSnapshotCreationReason = "GoldenSnapshotCreation" +) + +type ActorTemplateReconciler struct { + client.Client + Scheme *runtime.Scheme + + AteClient ateapipb.ControlClient +} + +//+kubebuilder:rbac:groups=ate.dev,resources=actortemplates,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=ate.dev,resources=actortemplates/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=ate.dev,resources=actortemplates/finalizers,verbs=update +//+kubebuilder:rbac:groups=ate.dev,resources=workerpools,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch +//+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +func (r *ActorTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + // Fetch actor template + at := &atev1alpha1.ActorTemplate{} + if err := r.Get(ctx, req.NamespacedName, at); err != nil { + if k8errors.IsNotFound(err) { + return ctrl.Result{}, nil + } + return ctrl.Result{}, fmt.Errorf("failed to get actor template %q: %w", req.NamespacedName, err) + } + + // Handle deletion + if !at.GetDeletionTimestamp().IsZero() { + return ctrl.Result{}, nil + } + + switch at.Status.Phase { + case atev1alpha1.PhaseInitial: + actorID := uuid.NewString() + + createReq := &ateapipb.CreateActorRequest{ + ActorId: actorID, + ActorTemplateNamespace: at.ObjectMeta.Namespace, + ActorTemplateName: at.ObjectMeta.Name, + } + _, err := r.AteClient.CreateActor(ctx, createReq) + if err != nil { + return ctrl.Result{}, fmt.Errorf("while creating golden actor: %w", err) + } + + at.Status.Phase = atev1alpha1.PhaseResumeGoldenActor + at.Status.GoldenActorID = actorID + if err := r.Status().Update(ctx, at); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + + case atev1alpha1.PhaseResumeGoldenActor: + + // TODO(ateom): If resumption fails because the ateom or atelet is not + // quite ready, we can end up leaking a worker that thinks it's assigned + // to the golden actor. We should persist the golden actor ID first, + // then drive resume as a separate step. + + // Resuming when the ActorTemplate has no golden snapshot results in the + // workload being freshly booted. + // + // TODO: Maybe this should go through a different RPC dedicated to + // booting an actor from scratch. + resumeReq := &ateapipb.ResumeActorRequest{ + ActorId: at.Status.GoldenActorID, + } + _, err := r.AteClient.ResumeActor(ctx, resumeReq) + if err != nil { + return ctrl.Result{}, fmt.Errorf("while resuming golden actor: %w", err) + } + + at.Status.Phase = atev1alpha1.PhaseWaitGoldenActor + at.Status.TakeGoldenSnapshotAt = metav1.NewTime(time.Now().Add(20 * time.Second)) + if err := r.Status().Update(ctx, at); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + + case atev1alpha1.PhaseWaitGoldenActor: + // Wait until the snapshot time. + rem := time.Until(at.Status.TakeGoldenSnapshotAt.Time) + if rem >= 0 { + return ctrl.Result{RequeueAfter: rem}, nil + } + + // TODO: Need to be more resilient --- if suspendactor tells us + // conflict, we should fetch the suspended actor and read the snapshot + // from it. + + req := &ateapipb.SuspendActorRequest{ + ActorId: at.Status.GoldenActorID, + } + resp, err := r.AteClient.SuspendActor(ctx, req) + if err != nil { + return ctrl.Result{}, fmt.Errorf("while suspending golden actor: %w", err) + } + + // Transition to PhaseReady + at.Status.GoldenSnapshot = resp.GetActor().GetLastSnapshot() + at.Status.Phase = atev1alpha1.PhaseReady + meta.SetStatusCondition(&at.Status.Conditions, metav1.Condition{ + Type: "Ready", + Status: metav1.ConditionTrue, + Reason: "Ready", + Message: "Actor template is ready for use", + }) + if err := r.Status().Update(ctx, at); err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil + case atev1alpha1.PhaseReady: + return ctrl.Result{}, nil + default: + return ctrl.Result{}, fmt.Errorf("unrecognized phase %q", at.Status.Phase) + } +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ActorTemplateReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr).For(&atev1alpha1.ActorTemplate{}).Complete(r) +} diff --git a/internal/controllers/gen.go b/internal/controllers/gen.go new file mode 100644 index 000000000..23b06e14e --- /dev/null +++ b/internal/controllers/gen.go @@ -0,0 +1,17 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controllers + +//go:generate bash ../../hack/run-tool.sh controller-gen rbac:headerFile=../../hack/boilerplate/yaml.txt,roleName=ate-controller paths="./..." output:rbac:artifacts:config=../../manifests/ate-install/generated/ diff --git a/internal/controllers/utils.go b/internal/controllers/utils.go new file mode 100644 index 000000000..ea275e5ce --- /dev/null +++ b/internal/controllers/utils.go @@ -0,0 +1,101 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controllers + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" +) + +// createActorDeploymentSpec creates a deployment spec for an actor. +func createActorDeploymentSpec(name string, replicas int32, wpName string, ateomImage string) *appsv1.DeploymentSpec { + ds := &appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": name, + }, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "app": name, + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "ateom", + Image: ateomImage, + Args: []string{ + "-pod-namespace=$(POD_NAMESPACE)", + "-pod-name=$(POD_NAME)", + }, + SecurityContext: &corev1.SecurityContext{ + Privileged: ptr.To(true), + RunAsUser: ptr.To(int64(0)), + RunAsGroup: ptr.To(int64(0)), + }, + Env: []corev1.EnvVar{ + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.name", + }, + }, + }, + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "run-ateom", + MountPath: "/run/ateom-gvisor", + }, + }, + }, + }, + SecurityContext: &corev1.PodSecurityContext{ + RunAsUser: ptr.To(int64(0)), + RunAsGroup: ptr.To(int64(0)), + }, + Volumes: []corev1.Volume{ + { + Name: "run-ateom", + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "/run/ateom-gvisor", + Type: ptr.To(corev1.HostPathDirectoryOrCreate), + }, + }, + }, + }, + }, + }, + } + if wpName != "" { + ds.Template.ObjectMeta.Labels["ate.dev/worker-pool"] = wpName + } + return ds +} diff --git a/internal/controllers/workerpool_controller.go b/internal/controllers/workerpool_controller.go new file mode 100644 index 000000000..2aed45849 --- /dev/null +++ b/internal/controllers/workerpool_controller.go @@ -0,0 +1,122 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package controllers + +import ( + "context" + "fmt" + + appsv1 "k8s.io/api/apps/v1" + k8errors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + atev1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/google/go-cmp/cmp" +) + +type WorkerPoolReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +//+kubebuilder:rbac:groups=ate.dev,resources=workerpools,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=ate.dev,resources=workerpools/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=ate.dev,resources=workerpools/finalizers,verbs=update +//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +func (r *WorkerPoolReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := log.FromContext(ctx) + + // Fetch worker pool + wp := &atev1alpha1.WorkerPool{} + if err := r.Get(ctx, req.NamespacedName, wp); err != nil { + if k8errors.IsNotFound(err) { + return ctrl.Result{}, nil + } + return ctrl.Result{}, fmt.Errorf("failed to get worker pool %q: %w", req.NamespacedName, err) + } + + // Handle deletion + if !wp.GetDeletionTimestamp().IsZero() { + log.Info("WorkerPool is being deleted") + return ctrl.Result{}, nil + } + + if err := r.reconcileWorkerPool(ctx, wp); err != nil { + log.Error(err, "Failed to reconcile worker pool, err: %v", err) + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil +} + +func (r *WorkerPoolReconciler) reconcileWorkerPool(ctx context.Context, wp *atev1alpha1.WorkerPool) error { + log := log.FromContext(ctx) + log.Info("Reconciling worker pool") + + depName := wp.Name + "-deployment" + + existingDeployment := &appsv1.Deployment{} + err := r.Get(ctx, types.NamespacedName{Name: depName, Namespace: wp.Namespace}, existingDeployment) + if err != nil { + if k8errors.IsNotFound(err) { + log.Info("Deployment for workerpool not found, creating a new one", "WorkPool.Name", wp.Name) + // 1. Create a new deployment when a new workerpool is created. + dep := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: depName, + Namespace: wp.Namespace, + }, + Spec: *createActorDeploymentSpec(wp.Name, wp.Spec.Replicas, wp.Name, wp.Spec.AteomImage), + } + + // 2. Setting the OwnerReference ensures Kubernetes garbage collects the deployment + // when the worker pool is deleted (Delete deployment when worker pool is deleted). + if err := ctrl.SetControllerReference(wp, dep, r.Scheme); err != nil { + return fmt.Errorf("failed to set controller reference: %w", err) + } + + log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) + if err := r.Create(ctx, dep); err != nil { + return fmt.Errorf("failed to create new Deployment: %w", err) + } + return nil + } + return fmt.Errorf("failed to get deployment %q: %w", depName, err) + } + + // TODO: Quick and dirty, stop using cmp.Diff + wantSpec := *createActorDeploymentSpec(wp.Name, wp.Spec.Replicas, wp.Name, wp.Spec.AteomImage) + if diff := cmp.Diff(existingDeployment.Spec, wantSpec); diff != "" { + existingDeployment.Spec = wantSpec + if err := r.Update(ctx, existingDeployment); err != nil { + return fmt.Errorf("failed to update Deployment replicas: %w", err) + } + } + + return nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *WorkerPoolReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr).For(&atev1alpha1.WorkerPool{}).Complete(r) +} diff --git a/internal/credbundle/credbundle.go b/internal/credbundle/credbundle.go new file mode 100644 index 000000000..a62d9555a --- /dev/null +++ b/internal/credbundle/credbundle.go @@ -0,0 +1,92 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package credbundle handles credential bundle files written by Kubernetes Pod Certificates. +// +// A credential bundle is a single file with multiple PEM entries. The first entry is a PRIVATE KEY +// block, and all remaining entries are CERTIFICATE blocks. The CERTIFICATE blocks are in +// leaf-to-root order, and may or may not include the root. +package credbundle + +import ( + "crypto/tls" + "crypto/x509" + "encoding/pem" + "fmt" + "os" +) + +// Loader reads a private key and certificate chain from a credential bundle file as written by the +// Kubernetes Pod Certificates mechanism. +// +// Returns a function that can be used as GetCertificate in a tls.Config +func Loader(path string) func(*tls.ClientHelloInfo) (*tls.Certificate, error) { + // TODO: Introduce caching. + return func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) { + return Parse(path) + } +} + +// Parse reads a private key and certificate chain from a credential bundle file as written by the +// Kubernetes Pod Certificates mechanism. +func Parse(bundlePath string) (*tls.Certificate, error) { + bundleBytes, err := os.ReadFile(bundlePath) + if err != nil { + return nil, fmt.Errorf("while reading credential bundle: %w", err) + } + + var leafKeyBytes []byte + var chainBytes [][]byte + + for { + var block *pem.Block + block, bundleBytes = pem.Decode(bundleBytes) + if block == nil { + break + } + + switch block.Type { + case "CERTIFICATE": + chainBytes = append(chainBytes, block.Bytes) + case "PRIVATE KEY": + leafKeyBytes = block.Bytes + default: + return nil, fmt.Errorf("unknown PEM block type %q", block.Type) + } + } + + if leafKeyBytes == nil { + return nil, fmt.Errorf("no PRIVATE KEY block found") + } + + if len(chainBytes) == 0 { + return nil, fmt.Errorf("no CERTIFICATE blocks found") + } + + leafKey, err := x509.ParsePKCS8PrivateKey(leafKeyBytes) + if err != nil { + return nil, fmt.Errorf("while parsing private key: %w", err) + } + + leafCert, err := x509.ParseCertificate(chainBytes[0]) + if err != nil { + return nil, fmt.Errorf("while parsing leaf certificate: %w", err) + } + + return &tls.Certificate{ + Certificate: chainBytes, + Leaf: leafCert, + PrivateKey: leafKey, + }, nil +} diff --git a/internal/dns/corefile.go b/internal/dns/corefile.go new file mode 100644 index 000000000..0a04fb959 --- /dev/null +++ b/internal/dns/corefile.go @@ -0,0 +1,63 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dns + +import ( + "fmt" + "strings" + "time" + + "github.com/agent-substrate/substrate/internal/resources" +) + +// corefileTemplate is a Sprintf template for the CoreDNS configuration. +var corefileTemplate string + +func init() { + corefileTemplate = buildTemplate() +} + +func buildTemplate() string { + // Build up the corefileTemplate programmatically to make it easier to understand. + var directives []string + // Plugins to enable. + directives = append(directives, "log") + directives = append(directives, "errors") + directives = append(directives, "health :8080") + directives = append(directives, "ready :8181") + directives = append(directives, "reload") + + // Construct match pattern for .. + directives = append(directives, fmt.Sprintf("template IN A %s {", resources.ActorDNSSuffix)) + dnsDomainParts := strings.Split("."+resources.ActorDNSSuffix+".", ".") + dnsDomainRef := strings.Join(dnsDomainParts, `\.`) + directives = append(directives, fmt.Sprintf(` match "^%s%s$"`, resources.ActorIDRegexPattern, dnsDomainRef)) + // Note the %s -- this will be filled with the router IP. + directives = append(directives, ` answer "{{ .Name }} 60 IN A %s"`) + directives = append(directives, "}") + + // Generate the template. + b := strings.Builder{} + fmt.Fprintf(&b, "# Generated at %s\n", time.Now()) + fmt.Fprintf(&b, "%s:53 {\n ", resources.ActorDNSSuffix) + fmt.Fprint(&b, strings.Join(directives, "\n ")) + fmt.Fprint(&b, "\n}\n") + + return b.String() +} + +func makeCoreFile(routerIP string) string { + return fmt.Sprintf(corefileTemplate, routerIP) +} diff --git a/internal/dns/corefile_test.go b/internal/dns/corefile_test.go new file mode 100644 index 000000000..6c0add6a2 --- /dev/null +++ b/internal/dns/corefile_test.go @@ -0,0 +1,65 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dns + +import ( + "strings" + "testing" + + "github.com/agent-substrate/substrate/internal/resources" +) + +func TestMakeCoreFile(t *testing.T) { + tests := []struct { + name string + routerIP string + expected []string + }{ + { + name: "standard local IP", + routerIP: "10.240.0.10", + expected: []string{ + "actors.resources.substrate.ate.dev:53 {", + "log", + "errors", + "health :8080", + "ready :8181", + "reload", + "template IN A actors.resources.substrate.ate.dev {", + `match "^` + resources.ActorIDRegexPattern + `\.actors\.resources\.substrate\.ate\.dev\.$"`, + `answer "{{ .Name }} 60 IN A 10.240.0.10"`, + }, + }, + { + name: "different IP", + routerIP: "192.168.1.1", + expected: []string{ + "actors.resources.substrate.ate.dev:53 {", + `answer "{{ .Name }} 60 IN A 192.168.1.1"`, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := makeCoreFile(tc.routerIP) + for _, exp := range tc.expected { + if !strings.Contains(got, exp) { + t.Errorf("makeCoreFile(%q) missing expected substring %q\nGot:\n%s", tc.routerIP, exp, got) + } + } + }) + } +} diff --git a/internal/dns/dns.go b/internal/dns/dns.go new file mode 100644 index 000000000..2e5d9d04a --- /dev/null +++ b/internal/dns/dns.go @@ -0,0 +1,252 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dns + +import ( + "context" + "encoding/json" + "fmt" + "log/slog" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + "time" + + "github.com/agent-substrate/substrate/internal/resources" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + // serviceName is the name of the CoreDNS service. + serviceName = "dns" + systemNamespace = "ate-system" +) + +// Controller manages the DNS configuration for the ATE. +type Controller struct { + Client client.Client + Interval time.Duration + CorefilePath string + Reloader ConfigReloader +} + +// Run the DNS orchestration loop until ctx is canceled. +func (c *Controller) Run(ctx context.Context) error { + slog.InfoContext(ctx, "DNS Controller started", slog.Duration("interval", c.Interval), slog.String("corefile", c.CorefilePath)) + slog.InfoContext(ctx, "Using template", "template", corefileTemplate) + + ticker := time.NewTicker(c.Interval) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + slog.InfoContext(ctx, "DNS Controller stopped") + return nil + case <-ticker.C: + if err := c.reconcile(ctx); err != nil { + slog.ErrorContext(ctx, "Error during DNS reconciliation", slog.Any("error", err)) + } + } + } +} + +func (c *Controller) reconcile(ctx context.Context) error { + slog.DebugContext(ctx, "Reconciling DNS orchestration configuration...") + + // 1. Get the ClusterIP of atenet-router in ate-system namespace + routerSvc := &corev1.Service{} + if err := c.Client.Get(ctx, types.NamespacedName{Name: "atenet-router", Namespace: systemNamespace}, routerSvc); err != nil { + if errors.IsNotFound(err) { + slog.WarnContext(ctx, "atenet-router service not found, skipping until it is available") + return nil + } + return fmt.Errorf("failed to get atenet-router service: %w", err) + } + + routerIP := routerSvc.Spec.ClusterIP + if routerIP == "" || routerIP == "None" { + slog.WarnContext(ctx, "atenet-router service has no ClusterIP yet, waiting...") + return nil + } + + // 2. Get the ClusterIP of dns service in ate-system namespace + dnsSvc := &corev1.Service{} + if err := c.Client.Get(ctx, types.NamespacedName{Name: serviceName, Namespace: systemNamespace}, dnsSvc); err != nil { + if errors.IsNotFound(err) { + slog.WarnContext(ctx, "dns service not found, skipping until it is available") + return nil + } + return fmt.Errorf("failed to get dns service: %w", err) + } + + dnsIP := dnsSvc.Spec.ClusterIP + if dnsIP == "" || dnsIP == "None" { + slog.WarnContext(ctx, "dns service has no ClusterIP yet, waiting...") + return nil + } + + // 3. Reconcile CoreDNS Corefile on shared volume + if err := c.reconcileCoreDNSConfig(ctx, routerIP); err != nil { + return fmt.Errorf("failed to reconcile CoreDNS config file: %w", err) + } + + // 4. Reconcile GKE kube-dns ConfigMap with dns service IP + if err := c.reconcileKubeDNSConfig(ctx, dnsIP); err != nil { + return fmt.Errorf("failed to reconcile kube-dns configmap: %w", err) + } + + return nil +} + +func (c *Controller) reconcileCoreDNSConfig(ctx context.Context, routerIP string) error { + expectedCorefile := makeCoreFile(routerIP) + + // Read Corefile from local shared volume path to see if it needs updating + corefileBytes, err := os.ReadFile(c.CorefilePath) + if err == nil && string(corefileBytes) == expectedCorefile { + slog.DebugContext(ctx, "CoreDNS Corefile is up-to-date", slog.String("routerIP", routerIP)) + return nil + } + + // Write updated Corefile back to shared volume in its entirety + if err := os.WriteFile(c.CorefilePath, []byte(expectedCorefile), 0644); err != nil { + return fmt.Errorf("failed to write updated Corefile to %s: %w", c.CorefilePath, err) + } + slog.InfoContext(ctx, "CoreDNS Corefile updated", slog.String("routerIP", routerIP)) + + // Signal CoreDNS process to reload + if err := c.Reloader.Reload(ctx); err != nil { + return fmt.Errorf("failed to reload CoreDNS: %w", err) + } + + return nil +} + +// reconcileKubeDNSConfig ensures that the kube-dns ConfigMap has a stub domain for ate-system. +func (c *Controller) reconcileKubeDNSConfig(ctx context.Context, dnsIP string) error { + cm := &corev1.ConfigMap{} + if err := c.Client.Get(ctx, types.NamespacedName{Name: "kube-dns", Namespace: "kube-system"}, cm); err != nil { + if errors.IsNotFound(err) { + slog.WarnContext(ctx, "kube-dns ConfigMap not found in kube-system namespace, skipping stub resolver configuration") + return nil + } + return fmt.Errorf("failed to retrieve kube-dns ConfigMap: %w", err) + } + + if cm.Data == nil { + cm.Data = make(map[string]string) + } + + stubDomainsStr := cm.Data["stubDomains"] + var stubDomains map[string][]string + + if stubDomainsStr != "" { + if err := json.Unmarshal([]byte(stubDomainsStr), &stubDomains); err != nil { + return fmt.Errorf("failed to parse stubDomains JSON: %w", err) + } + } else { + stubDomains = make(map[string][]string) + } + + ips, exists := stubDomains[resources.ActorDNSSuffix] + if exists && len(ips) == 1 && ips[0] == dnsIP { + slog.DebugContext(ctx, "kube-dns stubDomains are already up-to-date", slog.String("dnsIP", dnsIP)) + return nil + } + + stubDomains[resources.ActorDNSSuffix] = []string{dnsIP} + + newStubDomainsBytes, err := json.Marshal(stubDomains) + if err != nil { + return fmt.Errorf("failed to marshal stubDomains JSON: %w", err) + } + + cm.Data["stubDomains"] = string(newStubDomainsBytes) + if err := c.Client.Update(ctx, cm); err != nil { + return fmt.Errorf("failed to update kube-dns ConfigMap: %w", err) + } + + slog.InfoContext(ctx, "kube-dns stubDomains successfully updated with custom DNS IP", slog.String("dnsIP", dnsIP)) + return nil +} + +// ConfigReloader defines an interface for dynamically signaling CoreDNS to reload its configuration. +type ConfigReloader interface { + Reload(ctx context.Context) error +} + +type procConfigReloader struct{} + +func NewConfigReloader() ConfigReloader { + return &procConfigReloader{} +} + +func (r *procConfigReloader) Reload(ctx context.Context) error { + pid, err := findPID("coredns") + if err != nil { + slog.ErrorContext(ctx, "findPID error", slog.Any("error", err)) + return nil + } + + process, err := os.FindProcess(pid) + if err != nil { + return fmt.Errorf("FindProcess %d: %w", pid, err) + } + + // CoreDNS catches SIGUSR1 or SIGHUP to trigger dynamic reload of Corefile + if err := process.Signal(syscall.SIGUSR1); err != nil { + return fmt.Errorf("SendProcess SIGUSR1 %d: %w", pid, err) + } + + slog.InfoContext(ctx, "Successfully signaled reload", slog.Int("pid", pid)) + return nil +} + +func findPID(cmdName string) (int, error) { + files, err := os.ReadDir("/proc") + if err != nil { + return 0, fmt.Errorf("ReadDir /proc: %w", err) + } + + for _, file := range files { + if !file.IsDir() { + continue + } + + pid, err := strconv.Atoi(file.Name()) + if err != nil { + continue + } + + commBytes, err := os.ReadFile(filepath.Join("/proc", file.Name(), "comm")) + if err != nil { + // Process might have terminated + continue + } + + commGot := strings.TrimSpace(string(commBytes)) + if commGot == cmdName { + return pid, nil + } + } + + return 0, fmt.Errorf("%q process not found", cmdName) +} diff --git a/internal/dns/dns_test.go b/internal/dns/dns_test.go new file mode 100644 index 000000000..63dc4f73f --- /dev/null +++ b/internal/dns/dns_test.go @@ -0,0 +1,199 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dns + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "strings" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +type mockConfigReloader struct { + reloaded bool +} + +func (m *mockConfigReloader) Reload(ctx context.Context) error { + m.reloaded = true + return nil +} + +func TestReconcile(t *testing.T) { + scheme := runtime.NewScheme() + _ = corev1.AddToScheme(scheme) + + // 1. Create mock services + routerSvc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "atenet-router", + Namespace: "ate-system", + }, + Spec: corev1.ServiceSpec{ + ClusterIP: "10.0.0.1", + }, + } + + dnsSvc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dns", + Namespace: "ate-system", + }, + Spec: corev1.ServiceSpec{ + ClusterIP: "10.0.0.2", + }, + } + + initialCorefile := ` +.:53 { + errors +} +` + + // 2. Set up a temporary local Corefile on disk + tempDir := t.TempDir() + corefilePath := filepath.Join(tempDir, "Corefile") + if err := os.WriteFile(corefilePath, []byte(initialCorefile), 0644); err != nil { + t.Fatalf("failed to write initial Corefile: %v", err) + } + + kubeDNSCM := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kube-dns", + Namespace: "kube-system", + }, + Data: map[string]string{ + "stubDomains": `{"other-domain.com":["8.8.8.8"]}`, + }, + } + + client := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(routerSvc, dnsSvc, kubeDNSCM). + Build() + + reloader := &mockConfigReloader{} + controller := &Controller{ + Client: client, + Interval: 1 * time.Second, + CorefilePath: corefilePath, + Reloader: reloader, + } + + // Run one reconciliation loop + ctx := context.Background() + err := controller.reconcile(ctx) + if err != nil { + t.Fatalf("reconcile failed: %v", err) + } + + if !reloader.reloaded { + t.Errorf("expected ConfigReloader to be invoked, but it was not") + } + + // Verify the Corefile on disk has been updated with the router IP + updatedCorefileBytes, err := os.ReadFile(corefilePath) + if err != nil { + t.Fatalf("failed to read updated Corefile from disk: %v", err) + } + updatedCorefile := string(updatedCorefileBytes) + if !strings.Contains(updatedCorefile, `answer "{{ .Name }} 60 IN A 10.0.0.1"`) { + t.Errorf("expected Corefile on disk to contain updated answer line, but got: %s", updatedCorefile) + } + + // Verify kube-system:kube-dns ConfigMap contains the new stub domain without wiping out other-domain + updatedKubeDNSCM := &corev1.ConfigMap{} + err = client.Get(ctx, types.NamespacedName{Name: "kube-dns", Namespace: "kube-system"}, updatedKubeDNSCM) + if err != nil { + t.Fatalf("failed to get updated kube-dns ConfigMap: %v", err) + } + + stubDomainsStr := updatedKubeDNSCM.Data["stubDomains"] + var stubDomains map[string][]string + if err := json.Unmarshal([]byte(stubDomainsStr), &stubDomains); err != nil { + t.Fatalf("failed to unmarshal updated stubDomains: %v", err) + } + + ips, exists := stubDomains["actors.resources.substrate.ate.dev"] + if !exists || len(ips) != 1 || ips[0] != "10.0.0.2" { + t.Errorf("expected stubDomains to map actors.resources.substrate.ate.dev to [10.0.0.2], but got: %v", stubDomains) + } + + otherIPs, exists := stubDomains["other-domain.com"] + if !exists || len(otherIPs) != 1 || otherIPs[0] != "8.8.8.8" { + t.Errorf("expected stubDomains to preserve other-domain.com mapping, but got: %v", stubDomains) + } +} + +func TestReconcileKubeDNSNotFound(t *testing.T) { + scheme := runtime.NewScheme() + _ = corev1.AddToScheme(scheme) + + routerSvc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "atenet-router", + Namespace: "ate-system", + }, + Spec: corev1.ServiceSpec{ + ClusterIP: "10.0.0.1", + }, + } + + dnsSvc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dns", + Namespace: "ate-system", + }, + Spec: corev1.ServiceSpec{ + ClusterIP: "10.0.0.2", + }, + } + + // Set up local Corefile on disk + tempDir := t.TempDir() + corefilePath := filepath.Join(tempDir, "Corefile") + initialCorefile := `answer "{{ .Name }} 60 IN A "` + if err := os.WriteFile(corefilePath, []byte(initialCorefile), 0644); err != nil { + t.Fatalf("failed to write initial Corefile: %v", err) + } + + // kube-dns ConfigMap is omitted to test gracefulness + + client := fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(routerSvc, dnsSvc). + Build() + + controller := &Controller{ + Client: client, + Interval: 1 * time.Second, + CorefilePath: corefilePath, + Reloader: &mockConfigReloader{}, + } + + ctx := context.Background() + err := controller.reconcile(ctx) + if err != nil { + t.Fatalf("reconcile should handle missing kube-dns configmap gracefully but failed with: %v", err) + } +} diff --git a/internal/dns/readme.md b/internal/dns/readme.md new file mode 100644 index 000000000..5209cc607 --- /dev/null +++ b/internal/dns/readme.md @@ -0,0 +1,36 @@ +# DNS Controller + +The DNS Controller orchsterates the configuration needed to setup the ATE routing. + +We want to resolve requests for .actors.resources.substrate.ate.dev to the router service address. + +* Stub resolver mode: orchestrate running a CoreDNS instance with the UUID mapped to the router service address. + +Cluster resources: + +* Deployment `ate-system:dns`. Label: app=dns +* Service `ate-system:dns`. +* ConfigMap `ate-system:dns`. + +These are defined in manifests/ate-install/atenet-dns.yaml. + +## Stub resolver mode + +* Ensure stub resolver CoreDNS is running as: + * Deployment `ate-system:dns`. + * Service `ate-system:dns` pointing to the Deployment. + +ConfigMap `ate-system:dns`: + +``` +# Match any 'A' query for a UUID pattern under actors.resources.substrate.ate.dev + template IN A actors.resources.substrate.ate.dev { + match "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\.actors\\.resources\\.substrate\\.k8s\\.io\\.$" + answer "{{ .Name }} 60 IN A " + } +``` + +## Integration + +* CoreDNS: Update CoreDNS ConfigMap to add the stub resolver. +* GKE DNS: Update the GKE DNS ConfigMap to add the stub resolver. diff --git a/internal/e2e/clients.go b/internal/e2e/clients.go new file mode 100644 index 000000000..a71586db2 --- /dev/null +++ b/internal/e2e/clients.go @@ -0,0 +1,87 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "context" + "fmt" + "time" + + "github.com/agent-substrate/substrate/cmd/kubectl-ate/pkg/client" + "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/client-go/kubernetes" +) + +type Clients struct { + K8s *kubernetes.Clientset + CRD *apiextensionsclientset.Clientset + SubstrateK8s *versioned.Clientset + SubstrateAPI *client.Client +} + +var sharedClients *Clients + +// GetClients returns the shared E2E clients. +// It panics if the clients have not been initialized. +func GetClients() *Clients { + if sharedClients == nil { + panic("sharedClients not initialized. RunTestMain must be used to initialize clients.") + } + return sharedClients +} + +func NewClients(ctx context.Context) (*Clients, error) { + // Kube API + config, err := client.LoadConfig(KubeConfig, KubeContext) + if err != nil { + return nil, fmt.Errorf("LoadConfig error %q %s: %w", KubeConfig, KubeContext, err) + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("NewForConfig: %w", err) + } + + crdClient, err := apiextensionsclientset.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("apiextensions clientset: %w", err) + } + + substrateClient, err := versioned.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("substrate clientset: %w", err) + } + + // Establish port-forward tunnel and connect to ATE API + connectCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + + apiClient, err := client.NewClient(connectCtx, KubeConfig, KubeContext, "", false) + if err != nil { + return nil, fmt.Errorf("NewClient: %w", err) + } + + return &Clients{ + K8s: clientset, + CRD: crdClient, + SubstrateK8s: substrateClient, + SubstrateAPI: apiClient, + }, nil +} + +func (c *Clients) Close() { + c.SubstrateAPI.Close() +} diff --git a/internal/e2e/env.go b/internal/e2e/env.go new file mode 100644 index 000000000..ccc2e7f6b --- /dev/null +++ b/internal/e2e/env.go @@ -0,0 +1,34 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "fmt" + "os" +) + +// CheckEnv checks the list of env vars exist and returns their value. +// If any env var is not set, it returns an error. +func CheckEnv(keys ...string) (map[string]string, error) { + env := make(map[string]string, len(keys)) + for _, key := range keys { + value := os.Getenv(key) + if value == "" { + return nil, fmt.Errorf("environment variable %s is not set", key) + } + env[key] = value + } + return env, nil +} diff --git a/internal/e2e/env_test.go b/internal/e2e/env_test.go new file mode 100644 index 000000000..c15e44afb --- /dev/null +++ b/internal/e2e/env_test.go @@ -0,0 +1,93 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "os" + "reflect" + "testing" +) + +func TestCheckEnv(t *testing.T) { + // Preserve original env for clean testing environment, and restore it afterwards. + // Since CheckEnv reads actual environment variables, we will back up and restore any keys we modify. + testKeys := []string{"TEST_ENV_FOO", "TEST_ENV_BAR", "TEST_ENV_EMPTY"} + originalVals := make(map[string]string) + for _, key := range testKeys { + if val, ok := os.LookupEnv(key); ok { + originalVals[key] = val + } + defer func(k string) { + if val, ok := originalVals[k]; ok { + os.Setenv(k, val) + } else { + os.Unsetenv(k) + } + }(key) + } + + // Set up our test environment + os.Setenv("TEST_ENV_FOO", "value_foo") + os.Setenv("TEST_ENV_BAR", "value_bar") + os.Setenv("TEST_ENV_EMPTY", "") + + tests := []struct { + name string + keys []string + want map[string]string + wantErr bool + }{ + { + name: "all env vars present", + keys: []string{"TEST_ENV_FOO", "TEST_ENV_BAR"}, + want: map[string]string{ + "TEST_ENV_FOO": "value_foo", + "TEST_ENV_BAR": "value_bar", + }, + wantErr: false, + }, + { + name: "missing env var", + keys: []string{"TEST_ENV_FOO", "TEST_ENV_NONEXISTENT"}, + want: nil, + wantErr: true, + }, + { + name: "env var is empty string", + keys: []string{"TEST_ENV_FOO", "TEST_ENV_EMPTY"}, + want: nil, + wantErr: true, + }, + { + name: "no keys requested", + keys: []string{}, + want: map[string]string{}, + wantErr: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, err := CheckEnv(tc.keys...) + if (err != nil) != tc.wantErr { + t.Errorf("CheckEnv() error = %v, wantErr %v", err, tc.wantErr) + return + } + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("CheckEnv() = %v, want %v", got, tc.want) + } + }) + } +} diff --git a/internal/e2e/namespace.go b/internal/e2e/namespace.go new file mode 100644 index 000000000..e641ccc9b --- /dev/null +++ b/internal/e2e/namespace.go @@ -0,0 +1,147 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "context" + "fmt" + "math/rand" + "os" + "slices" + "strings" + "sync" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var ( + namespacesToCleanup []string + namespacesMu sync.Mutex + rnd = rand.New(rand.NewSource(time.Now().UnixNano())) +) + +// randomnamepaceName returns a random namespace name. +// Format is "aaaa-ddd" where a is a random letter and d is a random digit. +func randomNamespaceName() string { + const letters = "abcdefghijklmnopqrstuvwxyz" + const digits = "0123456789" + + var sb strings.Builder + for range 4 { + sb.WriteByte(letters[rnd.Intn(len(letters))]) + } + sb.WriteByte('-') + for range 3 { + sb.WriteByte(digits[rnd.Intn(len(digits))]) + } + return sb.String() +} + +type Namespace struct { + Name string +} + +// CreateNamespace creates a new namespace with a randomized name using the K8s API +// and registers it for cleanup at the end of the test. +func CreateNamespace(t *testing.T) *Namespace { + t.Helper() + + // Check that we didn't dupe a name in namespacesToCleanup + namespacesMu.Lock() + var nsName string + for range 1000 { + name := randomNamespaceName() + if !slices.Contains(namespacesToCleanup, name) { + namespacesToCleanup = append(namespacesToCleanup, name) + nsName = name + break + } + } + namespacesMu.Unlock() + + if nsName == "" { + // This should really never happen. + t.Fatalf("Failed to create unique namespace name.") + } + + t.Logf("Creating namespace: %s", nsName) + + clients := GetClients() + + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: nsName, + }, + } + + _, err := clients.K8s.CoreV1().Namespaces().Create(t.Context(), ns, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Failed to create namespace %s: %v", nsName, err) + } + + // Wait for namespace to be active + const timeout = 60 * time.Second + ctx, cancel := context.WithTimeout(t.Context(), timeout) + defer cancel() + for { + ns, err := clients.K8s.CoreV1().Namespaces().Get(ctx, nsName, metav1.GetOptions{}) + if err == nil && ns.Status.Phase == corev1.NamespaceActive { + break + } + select { + case <-ctx.Done(): + t.Fatalf("Timed out waiting for namespace %q to be active after %v: %v", nsName, timeout, err) + case <-time.After(200 * time.Millisecond): + // Keep polling. + } + } + + return &Namespace{Name: nsName} +} + +// Delete the namespace explicitly. This will fail the test if deletion fails. +func (ns *Namespace) Delete(t *testing.T) { + t.Helper() + err := sharedClients.K8s.CoreV1().Namespaces().Delete(t.Context(), ns.Name, metav1.DeleteOptions{}) + if err != nil { + t.Fatalf("Failed to delete namespace %s: %v", ns.Name, err) + } +} + +// CleanupNamespaces deletes all registered namespaces using the K8s API. +// This should be called at the end of RunTestMain. +func CleanupNamespaces() { + namespacesMu.Lock() + defer namespacesMu.Unlock() + + if len(namespacesToCleanup) == 0 { + return + } + + clients := GetClients() + + fmt.Printf("Cleaning up %d namespaces...\n", len(namespacesToCleanup)) + for _, ns := range namespacesToCleanup { + fmt.Printf("Deleting namespace %s...\n", ns) + err := clients.K8s.CoreV1().Namespaces().Delete(context.Background(), ns, metav1.DeleteOptions{}) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to delete namespace %s: %v\n", ns, err) + } + } + namespacesToCleanup = nil +} diff --git a/internal/e2e/preflight.go b/internal/e2e/preflight.go new file mode 100644 index 000000000..9d15dcdd5 --- /dev/null +++ b/internal/e2e/preflight.go @@ -0,0 +1,65 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "context" + "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/agent-substrate/substrate/proto/ateapipb" +) + +// PreflightChecks checks that the test environment is ready for the test suite. +func PreflightChecks() error { + ctx := context.Background() + + clients := GetClients() + + // List namespaces to verify connectivity + _, err := clients.K8s.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + return fmt.Errorf("failed to connect to Kubernetes API server: %v", err) + } + + // Check deployments. + deployments := []string{ + "ate-controller", + "ate-api-server-deployment", + } + namespace := "ate-system" + for _, depName := range deployments { + dep, err := clients.K8s.AppsV1().Deployments(namespace).Get(ctx, depName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("deployment %s/%s is missing: %v", namespace, depName, err) + } + if dep.Status.ReadyReplicas == 0 { + return fmt.Errorf("deployment %s/%s has 0 ready replicas. Status: %+v", namespace, depName, dep.Status) + } + } + + // Verify that we can call the API. + listCtx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + _, err = clients.SubstrateAPI.ListActors(listCtx, &ateapipb.ListActorsRequest{}) + if err != nil { + return fmt.Errorf("ListActors RPC failed: %v", err) + } + + return nil +} diff --git a/internal/e2e/pretty.go b/internal/e2e/pretty.go new file mode 100644 index 000000000..99efa20fa --- /dev/null +++ b/internal/e2e/pretty.go @@ -0,0 +1,179 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "bytes" + "fmt" + "io" + "os" + "regexp" +) + +// noColor() disables colors for tests running in environments without colored output. +var ( + NoColor bool + // envNoColor (see https://no-color.org/) + envNoColor bool +) + +const ( + ansiReset = "\033[0m" + ansiDim = "\033[2m" + ansiRed = "\033[31m" + ansiCyan = "\033[36m" + ansiGreen = "\033[32m" + ansiYellow = "\033[33m" + ansiBold = "\033[1m" +) + +type colorEntry struct { + name string + ansi string + re *regexp.Regexp +} + +var ( + colors []colorEntry +) + +func init() { + colors = append(colors, colorEntry{name: "cyan", ansi: ansiCyan}) + colors = append(colors, colorEntry{name: "green", ansi: ansiGreen}) + colors = append(colors, colorEntry{name: "red", ansi: ansiRed}) + colors = append(colors, colorEntry{name: "yellow", ansi: ansiYellow}) + colors = append(colors, colorEntry{name: "bold", ansi: ansiBold}) + colors = append(colors, colorEntry{name: "dim", ansi: ansiDim}) + colors = append(colors, colorEntry{name: "reset", ansi: ansiReset}) + + for i := range colors { + colors[i].re = regexp.MustCompile(fmt.Sprintf("(?s)<%s>(.*?)", colors[i].name, colors[i].name)) + } + + // """ + // Command-line software which adds ANSI color to its output by default + // should check for a NO_COLOR environment variable that, when present + // and not an empty string (regardless of its value), prevents the addition + // of ANSI color. + // """ -- https://no-color.org/ + envNoColor = os.Getenv("NO_COLOR") != "" +} + +func noColor() bool { + return NoColor || envNoColor +} + +// Colorf renders a formatted string with color directives: +// +// "Example text: this is green". +// +// Unterminated directives will be treated as literals. +func Colorf(format string, a ...any) string { + str := fmt.Sprintf(format, a...) + for _, c := range colors { + if noColor() { + str = c.re.ReplaceAllString(str, "$1") + } else { + str = c.re.ReplaceAllString(str, c.ansi+"$1"+ansiReset) + } + } + + return str +} + +// FColorf writes a formatted string with color directives to the given writer. +func FColorf(f io.Writer, format string, a ...any) error { + _, err := fmt.Fprint(f, Colorf(format, a...)) + return err +} + +// FColorfln writes a formatted string with color directives to the given writer, followed by a newline. +func FColorfln(f io.Writer, format string, a ...any) error { + return FColorf(f, format+"\n", a...) +} + +// ColorWriter wraps an io.Writer and forces all writes to be colored with the given ANSI code. +// It respects noColor(). +type ColorWriter struct { + W io.Writer + ANSI string +} + +// Write writes p to the underlying writer, wrapped in the ANSI color code and reset code. +func (cw *ColorWriter) Write(p []byte) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + if noColor() { + return cw.W.Write(p) + } + // Write color code + _, err = cw.W.Write([]byte(cw.ANSI)) + if err != nil { + return 0, err + } + // Write content + n, err = cw.W.Write(p) + if err != nil { + return n, err + } + // Write reset code + _, err = cw.W.Write([]byte(ansiReset)) + if err != nil { + return n, err + } + return n, nil +} + +// IndentWriter wraps an io.Writer and indents each line of output. +type IndentWriter struct { + W io.Writer + Val string + atLineStart bool +} + +// NewIndentWriter creates a new IndentWriter. +func NewIndentWriter(w io.Writer, indent string) *IndentWriter { + return &IndentWriter{ + W: w, + Val: indent, + atLineStart: true, + } +} + +// Write writes p to the underlying writer, inserting the indent string at the start of each line. +func (iw *IndentWriter) Write(p []byte) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + + var buf bytes.Buffer + for _, b := range p { + if iw.atLineStart { + buf.WriteString(iw.Val) + iw.atLineStart = false + } + buf.WriteByte(b) + if b == '\n' { + iw.atLineStart = true + } + } + + _, err = iw.W.Write(buf.Bytes()) + if err != nil { + return 0, err + } + return len(p), nil +} diff --git a/internal/e2e/pretty_test.go b/internal/e2e/pretty_test.go new file mode 100644 index 000000000..fee879f50 --- /dev/null +++ b/internal/e2e/pretty_test.go @@ -0,0 +1,334 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "bytes" + "testing" +) + +func TestColorf(t *testing.T) { + tests := []struct { + name string + noColor bool + format string + args []interface{} + want string + }{ + { + name: "single green tag", + noColor: false, + format: "This is green text", + want: "This is \033[32mgreen\033[0m text", + }, + { + name: "multiple green tags", + noColor: false, + format: "one and two", + want: "\033[32mone\033[0m and \033[32mtwo\033[0m", + }, + { + name: "different tags", + noColor: false, + format: "green and red and yellow", + want: "\033[32mgreen\033[0m and \033[31mred\033[0m and \033[33myellow\033[0m", + }, + { + name: "unterminated tag", + noColor: false, + format: "This is unterminated", + want: "This is unterminated", + }, + { + name: "formatting with tags", + noColor: false, + format: "User %s logged in", + args: []interface{}{"bowei"}, + want: "User \033[32mbowei\033[0m logged in", + }, + { + name: "multiline tag", + noColor: false, + format: "This is green\ntext", + want: "This is \033[32mgreen\ntext\033[0m", + }, + { + name: "color disabled - multiline tags stripped", + noColor: true, + format: "This is green\ntext", + want: "This is green\ntext", + }, + { + name: "color disabled - tags stripped", + noColor: true, + format: "This is green and red", + want: "This is green and red", + }, + { + name: "color disabled - unterminated remains", + noColor: true, + format: "This is unterminated", + want: "This is unterminated", + }, + { + name: "dim tag", + noColor: false, + format: "This is dim text", + want: "This is \033[2mdim\033[0m text", + }, + { + name: "color disabled - dim tag stripped", + noColor: true, + format: "This is dim text", + want: "This is dim text", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + NoColor = tc.noColor + defer func() { NoColor = false }() + + got := Colorf(tc.format, tc.args...) + if got != tc.want { + t.Errorf("Colorf() = %q, want %q", got, tc.want) + } + }) + } +} + +func TestFColorfAndFColorfln(t *testing.T) { + t.Run("FColorf", func(t *testing.T) { + var buf bytes.Buffer + NoColor = false + err := FColorf(&buf, "Hello %s", "world") + if err != nil { + t.Fatalf("FColorf failed: %v", err) + } + want := "Hello \033[32mworld\033[0m" + if buf.String() != want { + t.Errorf("FColorf output = %q, want %q", buf.String(), want) + } + }) + + t.Run("FColorfln", func(t *testing.T) { + var buf bytes.Buffer + NoColor = false + err := FColorfln(&buf, "Hello %s", "world") + if err != nil { + t.Fatalf("FColorfln failed: %v", err) + } + want := "Hello \033[32mworld\033[0m\n" + if buf.String() != want { + t.Errorf("FColorfln output = %q, want %q", buf.String(), want) + } + }) + + t.Run("FColorf no color", func(t *testing.T) { + var buf bytes.Buffer + NoColor = true + defer func() { NoColor = false }() + err := FColorf(&buf, "Hello %s", "world") + if err != nil { + t.Fatalf("FColorf failed: %v", err) + } + want := "Hello world" + if buf.String() != want { + t.Errorf("FColorf output = %q, want %q", buf.String(), want) + } + }) +} + +func TestColorWriter(t *testing.T) { + tests := []struct { + name string + noColor bool + ansi string + input string + want string + }{ + { + name: "color enabled - red", + noColor: false, + ansi: "\033[31m", + input: "hello", + want: "\033[31mhello\033[0m", + }, + { + name: "color enabled - dim", + noColor: false, + ansi: "\033[2m", + input: "world", + want: "\033[2mworld\033[0m", + }, + { + name: "color disabled", + noColor: true, + ansi: "\033[31m", + input: "hello", + want: "hello", + }, + { + name: "empty input", + noColor: false, + ansi: "\033[31m", + input: "", + want: "", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + NoColor = tc.noColor + defer func() { NoColor = false }() + + var buf bytes.Buffer + cw := &ColorWriter{W: &buf, ANSI: tc.ansi} + n, err := cw.Write([]byte(tc.input)) + if err != nil { + t.Fatalf("Write failed: %v", err) + } + if n != len(tc.input) { + t.Errorf("Write returned n = %d, want %d", n, len(tc.input)) + } + if buf.String() != tc.want { + t.Errorf("ColorWriter output = %q, want %q", buf.String(), tc.want) + } + }) + } +} + +func TestIndentWriter(t *testing.T) { + tests := []struct { + name string + indent string + inputs []string + want string + }{ + { + name: "single line", + indent: " ", + inputs: []string{"hello"}, + want: " hello", + }, + { + name: "multiple lines in one write", + indent: " ", + inputs: []string{"hello\nworld"}, + want: " hello\n world", + }, + { + name: "multiple writes", + indent: " ", + inputs: []string{"hello\n", "world"}, + want: " hello\n world", + }, + { + name: "newline at end", + indent: " ", + inputs: []string{"hello\n"}, + want: " hello\n", + }, + { + name: "empty writes", + indent: " ", + inputs: []string{"", "hello"}, + want: " hello", + }, + { + name: "write without newline then write with newline", + indent: " ", + inputs: []string{"hello ", "world\n"}, + want: " hello world\n", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + var buf bytes.Buffer + iw := NewIndentWriter(&buf, tc.indent) + for _, input := range tc.inputs { + n, err := iw.Write([]byte(input)) + if err != nil { + t.Fatalf("Write failed: %v", err) + } + if n != len(input) { + t.Errorf("Write returned n = %d, want %d", n, len(input)) + } + } + if buf.String() != tc.want { + t.Errorf("IndentWriter output = %q, want %q", buf.String(), tc.want) + } + }) + } +} + +func TestIndentAndColorChaining(t *testing.T) { + var buf bytes.Buffer + cyanWriter := &ColorWriter{W: &buf, ANSI: "\033[36m"} + iw := NewIndentWriter(cyanWriter, " ") + + NoColor = false + defer func() { NoColor = false }() + + _, err := iw.Write([]byte("hello\nworld\n")) + if err != nil { + t.Fatalf("Write failed: %v", err) + } + + want := "\033[36m hello\n world\n\033[0m" + if buf.String() != want { + t.Errorf("Chained output = %q, want %q", buf.String(), want) + } +} + +func TestEnvNoColor(t *testing.T) { + origEnvNoColor := envNoColor + origNoColor := NoColor + defer func() { + envNoColor = origEnvNoColor + NoColor = origNoColor + }() + + t.Run("envNoColor true disables color", func(t *testing.T) { + envNoColor = true + NoColor = false + + if !noColor() { + t.Errorf("noColor() = false, want true when envNoColor is true") + } + + got := Colorf("hello") + want := "hello" + if got != want { + t.Errorf("Colorf() = %q, want %q", got, want) + } + }) + + t.Run("envNoColor false allows color", func(t *testing.T) { + envNoColor = false + NoColor = false + + if noColor() { + t.Errorf("noColor() = true, want false when both are false") + } + + got := Colorf("hello") + want := "\033[32mhello\033[0m" + if got != want { + t.Errorf("Colorf() = %q, want %q", got, want) + } + }) +} diff --git a/internal/e2e/readme.md b/internal/e2e/readme.md new file mode 100644 index 000000000..7bddd63d9 --- /dev/null +++ b/internal/e2e/readme.md @@ -0,0 +1,39 @@ +# E2E testing + +```shell +$ source .ate-dev-env.sh +$ go test -v ./internal/e2e/suites/... -args -e2e +``` + +## Principles + +* Keep it simple -- use go test for the harness. +* e2e tests live under `internal/e2e/suites/` +* Each suite should implement TestMain using e2e.RunTestMain() + * e2e tests will be skipped for ordinary unit tests unless the `-e2e` flag + is set e.g. `go test ./internal/e2e/suites/... -args -e2e` +* Helper libraries live under `internal/e2e` +* Setup and Teardown are on a per-component basis and the component's + author's responsibility. + +## Preconditions + +The e2e tests assume you have a cluster setup with `hack/install.sh`. + +## Creating a new test suite + +Copy `testmain_test.go` from `internal/e2e/suites/example` into your new suite. It will +look like this: + +```go +func run(m *testing.M) int { + Setup() + defer Teardown() + // return allows the deferred Teardown to run. + return e2e.RunTestMain(m) +} + +func TestMain(m *testing.M) { os.Exit(run(m)) } +``` + +This will handle the standard flags and checks for running an e2e test suite. diff --git a/internal/e2e/run.go b/internal/e2e/run.go new file mode 100644 index 000000000..74af9108a --- /dev/null +++ b/internal/e2e/run.go @@ -0,0 +1,74 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +// FindRepoRoot traverses directories upward starting from the current working +// directory to locate the repository root containing the go.mod file. +func FindRepoRoot() (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("failed to get working directory: %w", err) + } + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir, nil + } + parent := filepath.Dir(dir) + if parent == dir { + return "", fmt.Errorf("repository root containing go.mod not found") + } + dir = parent + } +} + +// RunCmd executes the given command with arguments, piping stdout and stderr +// to standard outputs, and fails the test if the command returns an error. +func RunCmd(t *testing.T, name string, args ...string) { + t.Helper() + t.Logf("Running command: %s %s", name, strings.Join(args, " ")) + cmd := exec.Command(name, args...) + stdoutColor := &ColorWriter{W: os.Stdout, ANSI: ansiCyan} + cmd.Stdout = NewIndentWriter(stdoutColor, " ") + stderrColor := &ColorWriter{W: os.Stderr, ANSI: ansiRed} + cmd.Stderr = NewIndentWriter(stderrColor, " ") + if err := cmd.Run(); err != nil { + t.Fatalf("Command failed: %s %s: %v", name, strings.Join(args, " "), err) + } +} + +// RunCmdWithEnv executes the given command with custom environment variables +// appended to the current process environment, and fails the test if it returns an error. +func RunCmdWithEnv(t *testing.T, env []string, name string, args ...string) { + t.Helper() + t.Logf("Running command with custom env: %s %s", name, strings.Join(args, " ")) + cmd := exec.Command(name, args...) + cmd.Env = append(os.Environ(), env...) + stdoutColor := &ColorWriter{W: os.Stdout, ANSI: ansiCyan} + cmd.Stdout = NewIndentWriter(stdoutColor, " ") + stderrColor := &ColorWriter{W: os.Stderr, ANSI: ansiRed} + cmd.Stderr = NewIndentWriter(stderrColor, " ") + if err := cmd.Run(); err != nil { + t.Fatalf("Command failed: %s %s: %v", name, strings.Join(args, " "), err) + } +} diff --git a/internal/e2e/suites/demo/demo_test.go b/internal/e2e/suites/demo/demo_test.go new file mode 100644 index 000000000..eec216b2b --- /dev/null +++ b/internal/e2e/suites/demo/demo_test.go @@ -0,0 +1,162 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package demo + +import ( + "context" + "testing" + "time" + + "github.com/agent-substrate/substrate/api/v1alpha1" + "github.com/agent-substrate/substrate/internal/e2e" + "github.com/agent-substrate/substrate/proto/ateapipb" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestDemo3(t *testing.T) { + env, err := e2e.CheckEnv("BUCKET_NAME", "KO_DOCKER_REPO") + if err != nil { + t.Fatalf("CheckEnv failed: %v", err) + } + + // Create namespace + nsObj := e2e.CreateNamespace(t) + + ctx := context.Background() + clients := e2e.GetClients() + + // Query existing WorkerPool and ActorTemplate to get the resolved container images + existingWp, err := clients.SubstrateK8s.ApiV1alpha1().WorkerPools("ate-demo-counter").Get(ctx, "counter", metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get existing WorkerPool: %v", err) + } + + existingAt, err := clients.SubstrateK8s.ApiV1alpha1().ActorTemplates("ate-demo-counter").Get(ctx, "counter", metav1.GetOptions{}) + if err != nil { + t.Fatalf("failed to get existing ActorTemplate: %v", err) + } + + // Create WorkerPool + wp := &v1alpha1.WorkerPool{ + ObjectMeta: metav1.ObjectMeta{ + Name: "counter", + Namespace: nsObj.Name, + }, + Spec: v1alpha1.WorkerPoolSpec{ + Replicas: 5, + AteomImage: existingWp.Spec.AteomImage, + }, + } + _, err = clients.SubstrateK8s.ApiV1alpha1().WorkerPools(nsObj.Name).Create(ctx, wp, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("failed to create WorkerPool: %v", err) + } + + // Create ActorTemplate + at := &v1alpha1.ActorTemplate{ + ObjectMeta: metav1.ObjectMeta{ + Name: "counter", + Namespace: nsObj.Name, + }, + Spec: v1alpha1.ActorTemplateSpec{ + WorkerPoolRef: corev1.ObjectReference{ + Namespace: nsObj.Name, + Name: "counter", + }, + Runsc: existingAt.Spec.Runsc, + PauseImage: existingAt.Spec.PauseImage, + Containers: existingAt.Spec.Containers, + SnapshotsConfig: v1alpha1.SnapshotsConfig{ + Location: "gs://" + env["BUCKET_NAME"] + "/ate-demo-counter", + }, + }, + } + _, err = clients.SubstrateK8s.ApiV1alpha1().ActorTemplates(nsObj.Name).Create(ctx, at, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("failed to create ActorTemplate: %v", err) + } + + // Wait for ActorTemplate to be Ready (golden snapshot created) before creating an actor. + t.Logf("Waiting for ActorTemplate %s to be Ready...", at.Name) + const tmplTimeout = 90 * time.Second + tmplCtx, tmplCancel := context.WithTimeout(ctx, tmplTimeout) + defer tmplCancel() + var lastPhase v1alpha1.PhaseType + for { + curAt, err := clients.SubstrateK8s.ApiV1alpha1().ActorTemplates(nsObj.Name).Get(tmplCtx, at.Name, metav1.GetOptions{}) + if err == nil { + lastPhase = curAt.Status.Phase + if lastPhase == v1alpha1.PhaseReady { + t.Logf("ActorTemplate %s is Ready with golden snapshot %q", at.Name, curAt.Status.GoldenSnapshot) + break + } + if lastPhase == v1alpha1.PhaseFailed { + t.Fatalf("ActorTemplate %s transitioned to PhaseFailed!", at.Name) + } + } + select { + case <-tmplCtx.Done(): + t.Fatalf("Timed out waiting for ActorTemplate %q to be Ready after %v (last phase: %s, err: %v)", at.Name, tmplTimeout, lastPhase, err) + case <-time.After(1 * time.Second): + // Keep polling. + } + } + + // Create an Actor using the ATE API. + actorID := "demo-actor-1-" + nsObj.Name + + t.Logf("Creating Actor %q using Substrate API...", actorID) + createResp, err := clients.SubstrateAPI.CreateActor(ctx, &ateapipb.CreateActorRequest{ + ActorId: actorID, + ActorTemplateNamespace: nsObj.Name, + ActorTemplateName: at.Name, + }) + if err != nil { + t.Fatalf("failed to create Actor: %v", err) + } + t.Logf("Successfully created Actor: %s", createResp.GetActor().GetActorId()) + + listResp, err := clients.SubstrateAPI.ListActors(ctx, &ateapipb.ListActorsRequest{}) + if err != nil { + t.Fatalf("ListActors RPC failed: %v", err) + } + + var myActors []*ateapipb.Actor + for _, actor := range listResp.GetActors() { + if actor.GetActorTemplateNamespace() == nsObj.Name && actor.GetActorId() == actorID { + myActors = append(myActors, actor) + } + } + + // Check that we have our Actor created. + if len(myActors) != 1 { + t.Fatalf("expected actor %s in namespace %s, got %d actors: %v", actorID, nsObj.Name, len(myActors), myActors) + } + + actor := myActors[0] + if actor.GetActorId() != actorID { + t.Errorf("expected actor ID %s, got %s", actorID, actor.GetActorId()) + } + if actor.GetActorTemplateName() != at.Name { + t.Errorf("expected actor template name %s, got %s", at.Name, actor.GetActorTemplateName()) + } + if actor.Status != ateapipb.Actor_STATUS_SUSPENDED { + t.Errorf("expected actor status to be SUSPENDED, got %v", actor.Status) + } + + t.Logf("Successfully queried Substrate API. Found %d active actors total, %d in our namespace %s.", + len(listResp.GetActors()), len(myActors), nsObj.Name) +} diff --git a/internal/e2e/suites/demo/testmain_test.go b/internal/e2e/suites/demo/testmain_test.go new file mode 100644 index 000000000..2d8a7e75e --- /dev/null +++ b/internal/e2e/suites/demo/testmain_test.go @@ -0,0 +1,24 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package demo + +import ( + "os" + "testing" + + "github.com/agent-substrate/substrate/internal/e2e" +) + +func TestMain(m *testing.M) { os.Exit(e2e.RunTestMain(m)) } diff --git a/internal/e2e/suites/example/example_test.go b/internal/e2e/suites/example/example_test.go new file mode 100644 index 000000000..64aca0214 --- /dev/null +++ b/internal/e2e/suites/example/example_test.go @@ -0,0 +1,23 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package example + +import ( + "testing" +) + +func TestExample(t *testing.T) { + t.Log("TestExample PASSED") +} diff --git a/internal/e2e/suites/example/testmain_test.go b/internal/e2e/suites/example/testmain_test.go new file mode 100644 index 000000000..98403ab2d --- /dev/null +++ b/internal/e2e/suites/example/testmain_test.go @@ -0,0 +1,39 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package example + +import ( + "os" + "testing" + + "github.com/agent-substrate/substrate/internal/e2e" +) + +func Setup() { + // setup code +} + +func Teardown() { + // teardown code +} + +func run(m *testing.M) int { + Setup() + defer Teardown() + // return allows the deferred Teardown to run. + return e2e.RunTestMain(m) +} + +func TestMain(m *testing.M) { os.Exit(run(m)) } diff --git a/internal/e2e/testmain.go b/internal/e2e/testmain.go new file mode 100644 index 000000000..74f8ba2c9 --- /dev/null +++ b/internal/e2e/testmain.go @@ -0,0 +1,74 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2e + +import ( + "context" + "flag" + "fmt" + "testing" +) + +var ( + RunE2E bool + KubeConfig string + KubeContext string +) + +func bindFlags() { + flag.BoolVar(&RunE2E, "e2e", false, "run e2e tests") + flag.BoolVar(&NoColor, "no-color", false, "disable colors in output") + flag.StringVar(&KubeConfig, "kube-config", "", "Location of the kubeconfig") + flag.StringVar(&KubeContext, "kube-context", "", "Kubernetes context to use") +} + +// RunTestMain should be used to run your e2e test suite. +func RunTestMain(m *testing.M) int { + bindFlags() + flag.Parse() + + if !RunE2E { + fmt.Println(Colorf(` + This is an e2e test suite and does not run by default. + Run with "go test ./internal/e2e/... -args -e2e"`)) + fmt.Println() + return 0 + } + + return runAndCleanup(m) +} + +func runAndCleanup(m *testing.M) int { + ctx := context.Background() + clients, err := NewClients(ctx) + if err != nil { + fmt.Printf("Failed to initialize E2E clients: %v\n", err) + return 1 + } + sharedClients = clients + defer func() { + sharedClients.Close() + sharedClients = nil + }() + + if err := PreflightChecks(); err != nil { + fmt.Println(Colorf("Preflight checks FAILED: %v\n", err)) + return 1 + } + + defer CleanupNamespaces() + + return m.Run() +} diff --git a/internal/k8sjwt/k8sjwt.go b/internal/k8sjwt/k8sjwt.go new file mode 100644 index 000000000..46e783293 --- /dev/null +++ b/internal/k8sjwt/k8sjwt.go @@ -0,0 +1,450 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package k8sjwt provides a JWT verifier tailored to Kubernetes. +package k8sjwt + +import ( + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "encoding/base64" + "encoding/json" + "fmt" + "hash" + "io" + "log/slog" + "math/big" + "net/http" + "slices" + "strings" + "time" +) + +// KeyAndID wraps a crypto.PublicKey along with the key ID that will identify it during +// the verification process. +// +// Use GKEKeyIDForLocallyStoredKey and GKEKeyIDForCloudKMSKey to get the correct key ID the way we +// calculate it in GKE. +type KeyAndID struct { + KeyID string + PublicKey crypto.PublicKey +} + +type parseHeader struct { + Type string `json:"typ,omitempty"` + Algorithm string `json:"alg,omitempty"` + KeyID string `json:"kid,omitempty"` +} + +type parseClaims struct { + // Claims from RFC7519 + Issuer string `json:"iss,omitempty"` + Subject string `json:"sub,omitempty"` + Audiences json.RawMessage `json:"aud,omitempty"` + Expiration float64 `json:"exp,omitempty"` + NotBefore float64 `json:"nbf,omitempty"` + IssuedAt float64 `json:"iat,omitempty"` + JTI string `json:"jti,omitempty"` + + // Kubernetes bound token claims. + BoundClaims parseBoundClaims `json:"kubernetes.io,omitempty"` + + // Kubernetes legacy token claims. + LegacyNamespace string `json:"kubernetes.io/serviceaccount/namespace,omitempty"` + LegacySecretName string `json:"kubernetes.io/serviceaccount/secret.name,omitempty"` + LegacyServiceAccountName string `json:"kubernetes.io/serviceaccount/service-account.name,omitempty"` + LegacyServiceAccountUID string `json:"kubernetes.io/serviceaccount/service-account.uid,omitempty"` +} + +type parseBoundClaims struct { + Namespace string `json:"namespace,omitempty"` + Pod parseBoundObjectReference `json:"pod,omitempty"` + ServiceAccount parseBoundObjectReference `json:"serviceaccount,omitempty"` + Secret parseBoundObjectReference `json:"secret,omitempty"` + Node parseBoundObjectReference `json:"node,omitempty"` + WarnAfter float64 `json:"warnafter,omitempty"` +} + +type parseBoundObjectReference struct { + Name string `json:"name,omitempty"` + UID string `json:"uid,omitempty"` +} + +// KubernetesClaims covers the claims that can be extracted from a newer Kubernetes bound service +// account JWT. +type KubernetesClaims struct { + // Claims from RFC7519 + Issuer string + Subject string + Audiences []string + Expiration time.Time + NotBefore time.Time + IssuedAt time.Time + JTI string + + Namespace string + + ServiceAccountName string + ServiceAccountUID string + PodName string + PodUID string + SecretName string + SecretUID string + NodeName string + NodeUID string + + WarnAfter time.Time +} + +var permittedSkew = 5 * time.Minute + +// Verify verifies and extracts claims from a Kubernetes JWT. +// +// For bound service account tokens, this function performs cryptographic verification of the JWT, +// checks the issuer and audience claims, and checks the time-binding claims. It *does not* check +// the object binding claims. If needed for your use case, you will need check the object bindings +// by connecting to the cluster and seeing if the object(s) the bindings name still exist within the +// cluster. +func Verify(ctx context.Context, jwt string, expectedIssuer, expectedAudience string, now time.Time) (*KubernetesClaims, error) { + segments := strings.Split(jwt, ".") + if len(segments) != 3 { + return nil, fmt.Errorf("malformed JWT") + } + headerB64String := segments[0] + payloadB64String := segments[1] + signatureB64String := segments[2] + + headerBytes, err := base64.RawURLEncoding.DecodeString(headerB64String) + if err != nil { + return nil, fmt.Errorf("while base64 decoding header: %w", err) + } + + signatureBytes, err := base64.RawURLEncoding.DecodeString(signatureB64String) + if err != nil { + return nil, fmt.Errorf("while base64 decoding signature: %w", err) + } + + var header parseHeader + if err := json.Unmarshal([]byte(headerBytes), &header); err != nil { + return nil, fmt.Errorf("while unmarshaling header: %w", err) + } + + // K8s JWTs don't set the `typ` header field. They might in the future, so we should tolerate the + // spec-recommended value. + switch header.Type { + case "", "JWT": // OK + default: + return nil, fmt.Errorf("unexpected value in type header") + } + + // Parse the payload. The payload is not verified at this point, so the only safe thing to do with + // it is extract the issuer, check the issuer, and fetch keys from the issuer. + // + // Don't consider any other data in the payload until the call to verifySignature() below. + payloadBytes, err := base64.RawURLEncoding.DecodeString(payloadB64String) + if err != nil { + return nil, fmt.Errorf("while base64-decoding payload: %w", err) + } + var rawClaims parseClaims + if err := json.Unmarshal(payloadBytes, &rawClaims); err != nil { + return nil, fmt.Errorf("while unmarshaling payload: %w", err) + } + + if rawClaims.Issuer != expectedIssuer { + return nil, fmt.Errorf("unexpected issuer %q", rawClaims.Issuer) + } + + // TODO: Cache keys, and only fetch new keys if the JWT's key ID is not in the cache. + keys, err := discoverKeysForIssuer(ctx, rawClaims.Issuer) + if err != nil { + return nil, fmt.Errorf("while discovering keys from issuer: %w", err) + } + + // Find the key we should use for verification based on the key ID in the JWT header. + if header.KeyID == "" { + return nil, fmt.Errorf("key ID is required") + } + selectedKeyIndex := slices.IndexFunc(keys, func(k *KeyAndID) bool { + return k.KeyID == header.KeyID + }) + if selectedKeyIndex == -1 { + return nil, fmt.Errorf("unknown key ID %q", header.KeyID) + } + selectedKey := keys[selectedKeyIndex].PublicKey + + // Warning: don't ever refer to the payload data (except "iss") above this point. We need to + // ensure that we _never_ consider the contents of the payload when deciding how to perform + // signature verification. + if err := verifySignature(header.Algorithm, selectedKey, []byte(headerB64String+"."+payloadB64String), signatureBytes); err != nil { + return nil, fmt.Errorf("while verifying JWT signature: %w", err) + } + + // It is now safe to consider arbitrary data from the payload. + // + // At this point, the payload is mostly trusted. We know that it was really issued by the selected + // verification key, but we need to check the issuer, audience binding, and time bindings to be + // sure that it's really valid. + + // Because the JWT spec authors wanted to be fancy, we need to try to deserialize + // rawClaims.Audience both as a single string and as a slice of strings. + var singleAudience string + var audiences []string + if err := json.Unmarshal(rawClaims.Audiences, &singleAudience); err == nil { // err EQUALS nil + audiences = []string{singleAudience} + } else if err := json.Unmarshal(rawClaims.Audiences, &audiences); err == nil { // err EQUALS nil + } else { + return nil, fmt.Errorf("unable to parse audiences") + } + + // Check that our expected audience is one of the audiences in the token + if !slices.Contains(audiences, expectedAudience) { + return nil, fmt.Errorf("token is not issued for expected audience") + } + + expiration := time.Unix(int64(rawClaims.Expiration), 0) + notBefore := time.Unix(int64(rawClaims.NotBefore), 0) + issuedAt := time.Unix(int64(rawClaims.IssuedAt), 0) + + if expiration.Before(now.Add(-permittedSkew)) { + return nil, fmt.Errorf("jwt has expired") + } + + if notBefore.After(now.Add(permittedSkew)) { + return nil, fmt.Errorf("jwt is not valid yet") + } + + if issuedAt.After(now.Add(permittedSkew)) { + return nil, fmt.Errorf("jwt claims to have been issued in the future") + } + + return &KubernetesClaims{ + Issuer: rawClaims.Issuer, + Audiences: audiences, + Subject: rawClaims.Subject, + Expiration: expiration, + NotBefore: notBefore, + IssuedAt: issuedAt, + JTI: rawClaims.JTI, + + Namespace: rawClaims.BoundClaims.Namespace, + ServiceAccountName: rawClaims.BoundClaims.ServiceAccount.Name, + ServiceAccountUID: rawClaims.BoundClaims.ServiceAccount.UID, + PodName: rawClaims.BoundClaims.Pod.Name, + PodUID: rawClaims.BoundClaims.Pod.UID, + SecretName: rawClaims.BoundClaims.Secret.Name, + SecretUID: rawClaims.BoundClaims.Secret.UID, + NodeName: rawClaims.BoundClaims.Node.Name, + NodeUID: rawClaims.BoundClaims.Node.UID, + + WarnAfter: time.Unix(int64(rawClaims.BoundClaims.WarnAfter), 0), + }, nil +} + +func verifySignature(algorithm string, selectedKey crypto.PublicKey, toBeSignedBytes, signatureBytes []byte) error { + switch algorithm { + case "RS256": + rsaKey, ok := selectedKey.(*rsa.PublicKey) + if !ok { + return fmt.Errorf("requested key ID is not an RSA key") + } + toBeSignedDigest := hashBytes(crypto.SHA256.New(), toBeSignedBytes) + if err := rsa.VerifyPKCS1v15(rsaKey, crypto.SHA256, toBeSignedDigest, signatureBytes); err != nil { + return fmt.Errorf("while validating RSA PKCS1v15 signature: %w", err) + } + case "RS384": + rsaKey, ok := selectedKey.(*rsa.PublicKey) + if !ok { + return fmt.Errorf("requested key ID is not an RSA key") + } + toBeSignedDigest := hashBytes(crypto.SHA384.New(), toBeSignedBytes) + if err := rsa.VerifyPKCS1v15(rsaKey, crypto.SHA384, toBeSignedDigest, signatureBytes); err != nil { + return fmt.Errorf("while validating RSA PKCS1v15 signature: %w", err) + } + case "RS512": + rsaKey, ok := selectedKey.(*rsa.PublicKey) + if !ok { + return fmt.Errorf("requested key ID is not an RSA key") + } + toBeSignedDigest := hashBytes(crypto.SHA512.New(), toBeSignedBytes) + if err := rsa.VerifyPKCS1v15(rsaKey, crypto.SHA512, toBeSignedDigest, signatureBytes); err != nil { + return fmt.Errorf("while validating RSA PKCS1v15 signature: %w", err) + } + case "ES256": + ecdsaKey, ok := selectedKey.(*ecdsa.PublicKey) + if !ok || ecdsaKey.Curve != elliptic.P256() { + return fmt.Errorf("requested key ID is not an ECDSA P256 key") + } + toBeSignedDigest := hashBytes(crypto.SHA256.New(), toBeSignedBytes) + if len(signatureBytes) != 2*32 { + return fmt.Errorf("invalid ecdsa signature") + } + r := big.NewInt(0).SetBytes(signatureBytes[:32]) + s := big.NewInt(0).SetBytes(signatureBytes[32:]) + if !ecdsa.Verify(ecdsaKey, toBeSignedDigest, r, s) { + return fmt.Errorf("invalid ecdsa signature") + } + case "ES384": + ecdsaKey, ok := selectedKey.(*ecdsa.PublicKey) + if !ok || ecdsaKey.Curve != elliptic.P384() { + return fmt.Errorf("requested key ID is not an ECDSA P256 key") + } + toBeSignedDigest := hashBytes(crypto.SHA384.New(), toBeSignedBytes) + if len(signatureBytes) != 2*48 { + return fmt.Errorf("invalid ecdsa signature") + } + r := big.NewInt(0).SetBytes(signatureBytes[:48]) + s := big.NewInt(0).SetBytes(signatureBytes[48:]) + if !ecdsa.Verify(ecdsaKey, toBeSignedDigest, r, s) { + return fmt.Errorf("invalid ecdsa signature") + } + case "ES512": + ecdsaKey, ok := selectedKey.(*ecdsa.PublicKey) + if !ok || ecdsaKey.Curve != elliptic.P521() { + return fmt.Errorf("requested key ID is not an ECDSA P256 key") + } + toBeSignedDigest := hashBytes(crypto.SHA512.New(), toBeSignedBytes) + if len(signatureBytes) != 2*66 { + return fmt.Errorf("invalid ecdsa signature") + } + r := big.NewInt(0).SetBytes(signatureBytes[:66]) + s := big.NewInt(0).SetBytes(signatureBytes[66:]) + if !ecdsa.Verify(ecdsaKey, toBeSignedDigest, r, s) { + return fmt.Errorf("invalid ecdsa signature") + } + default: + return fmt.Errorf("unsupported algorithm %q", algorithm) + } + + return nil +} + +func hashBytes(hasher hash.Hash, bytes []byte) []byte { + hasher.Write(bytes) + hash := hasher.Sum(nil) + return hash[:] +} + +type oidcConfigT struct { + JWKSURI string `json:"jwks_uri"` +} + +type jwkSetT struct { + Keys []jwkT `json:"keys"` +} + +type jwkT struct { + KeyType string `json:"kty"` + KeyID string `json:"kid,omitempty"` + + EllipticCurve string `json:"crv,omitempty"` + EllipticX string `json:"x,omitempty"` + EllipticY string `json:"y,omitempty"` + + RSAN string `json:"n"` + RSAE string `json:"e"` +} + +func discoverKeysForIssuer(ctx context.Context, issuer string) ([]*KeyAndID, error) { + var discoveryDocURL string + if strings.HasSuffix(issuer, "/") { + discoveryDocURL = issuer + ".well-known/openid-configuration" + } else { + discoveryDocURL = issuer + "/.well-known/openid-configuration" + } + + oidcConfig, err := fetchJSON[oidcConfigT](discoveryDocURL) + if err != nil { + return nil, fmt.Errorf("while fetching OIDC Discovery document: %w", err) + } + + slog.InfoContext(ctx, "Fetched discovery doc", slog.Any("doc", oidcConfig)) + + jwkSet, err := fetchJSON[jwkSetT](oidcConfig.JWKSURI) + if err != nil { + return nil, fmt.Errorf("while fetching JWKS: %w", err) + } + + slog.InfoContext(ctx, "Fetched JWK set", slog.Any("jwkSet", jwkSet)) + + var ret []*KeyAndID + for _, jwk := range jwkSet.Keys { + if jwk.KeyID == "" { + return nil, fmt.Errorf("JWKs endpoint returned key without key ID") + } + + switch jwk.KeyType { + case "EC": + switch jwk.EllipticCurve { + default: + return nil, fmt.Errorf("unhandled elliptic curve %q", jwk.EllipticCurve) + } + + case "RSA": + nBytes, err := base64.RawURLEncoding.DecodeString(jwk.RSAN) + if err != nil { + return nil, fmt.Errorf("while base64-decoding n: %w", err) + } + n := &big.Int{} + n.SetBytes(nBytes) + + eBytes, err := base64.RawURLEncoding.DecodeString(jwk.RSAE) + if err != nil { + return nil, fmt.Errorf("while base64-decoding e: %w", err) + } + e := &big.Int{} + e.SetBytes(eBytes) + + ret = append(ret, &KeyAndID{ + KeyID: jwk.KeyID, + PublicKey: &rsa.PublicKey{ + N: n, + E: int(e.Int64()), + }, + }) + + default: + return nil, fmt.Errorf("unhandled key type %q", jwk.KeyType) + } + } + + return ret, nil +} + +func fetchJSON[T any](url string) (T, error) { + var parsedBody T + + resp, err := http.Get(url) + if err != nil { + return parsedBody, fmt.Errorf("while making HTTP request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return parsedBody, fmt.Errorf("non-200 response code %d", resp.StatusCode) + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return parsedBody, fmt.Errorf("while reading response body: %w", err) + } + + if err := json.Unmarshal(bodyBytes, &parsedBody); err != nil { + return parsedBody, fmt.Errorf("while parsing response body: %w", err) + } + + return parsedBody, nil +} diff --git a/internal/localca/localca.go b/internal/localca/localca.go new file mode 100644 index 000000000..00376368f --- /dev/null +++ b/internal/localca/localca.go @@ -0,0 +1,152 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package localca implements a CA whose state can be stored in a local file or +// Kubernetes secret. +package localca + +import ( + "crypto" + "crypto/ed25519" + "crypto/rand" + "crypto/x509" + "encoding/json" + "fmt" + "time" +) + +type Pool struct { + CAs []*CA +} + +type CA struct { + ID string + SigningKey crypto.PrivateKey + RootCertificate *x509.Certificate + IntermediateCertificates []*x509.Certificate +} + +type serializedPool struct { + CAs []*serializedCA +} +type serializedCA struct { + ID string + SigningKeyPKCS8 []byte + RootCertificateDER []byte + IntermediateCertificatesDER [][]byte +} + +func Marshal(ca *Pool) ([]byte, error) { + wire := &serializedPool{} + + for _, ca := range ca.CAs { + caWire := &serializedCA{} + + caWire.ID = ca.ID + + signingKeyPKCS8, err := x509.MarshalPKCS8PrivateKey(ca.SigningKey) + if err != nil { + return nil, fmt.Errorf("while serializing signing key to PKCS#8: %w", err) + } + + caWire.SigningKeyPKCS8 = signingKeyPKCS8 + caWire.RootCertificateDER = ca.RootCertificate.Raw + for _, intermediate := range ca.IntermediateCertificates { + caWire.IntermediateCertificatesDER = append(caWire.IntermediateCertificatesDER, intermediate.Raw) + } + + wire.CAs = append(wire.CAs, caWire) + } + + wireBytes, err := json.Marshal(wire) + if err != nil { + return nil, fmt.Errorf("while marshaling to JSON: %w", err) + } + + return wireBytes, nil +} + +func Unmarshal(wireBytes []byte) (*Pool, error) { + var err error + wire := &serializedPool{} + + if err := json.Unmarshal(wireBytes, wire); err != nil { + return nil, fmt.Errorf("while unmarshaling JSON: %w", err) + } + + pool := &Pool{} + + for _, wireCA := range wire.CAs { + ca := &CA{ + ID: wireCA.ID, + } + + ca.SigningKey, err = x509.ParsePKCS8PrivateKey(wireCA.SigningKeyPKCS8) + if err != nil { + return nil, fmt.Errorf("while parsing signing key: %w", err) + } + + ca.RootCertificate, err = x509.ParseCertificate(wireCA.RootCertificateDER) + if err != nil { + return nil, fmt.Errorf("while parsing root certificate: %w", err) + } + + for _, intermediateDER := range wireCA.IntermediateCertificatesDER { + intermediateCert, err := x509.ParseCertificate(intermediateDER) + if err != nil { + return nil, fmt.Errorf("while parsing intermediate certificate: %w", err) + } + ca.IntermediateCertificates = append(ca.IntermediateCertificates, intermediateCert) + } + + pool.CAs = append(pool.CAs, ca) + } + + return pool, nil +} + +func GenerateED25519CA(id string) (*CA, error) { + rootPubKey, rootPrivKey, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return nil, fmt.Errorf("while generating root key: %w", err) + } + + notBefore := time.Now() + notAfter := notBefore.Add(365 * 24 * time.Hour) + + rootTemplate := &x509.Certificate{ + NotBefore: notBefore, + NotAfter: notAfter, + IsCA: true, + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + } + + rootDER, err := x509.CreateCertificate(rand.Reader, rootTemplate, rootTemplate, rootPubKey, rootPrivKey) + if err != nil { + return nil, fmt.Errorf("while generating root certificate: %w", err) + } + + rootCert, err := x509.ParseCertificate(rootDER) + if err != nil { + return nil, fmt.Errorf("while parsing root certificate: %w", err) + } + + return &CA{ + ID: id, + SigningKey: rootPrivKey, + RootCertificate: rootCert, + // No intermediates. + }, nil +} diff --git a/internal/localjwtauthority/localjwtauthority.go b/internal/localjwtauthority/localjwtauthority.go new file mode 100644 index 000000000..ca8b86487 --- /dev/null +++ b/internal/localjwtauthority/localjwtauthority.go @@ -0,0 +1,113 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package localjwtauthority implements a simple "CA" for JWTs. +package localjwtauthority + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "encoding/json" + "fmt" +) + +type Pool struct { + Authorities []*Authority +} + +type Authority struct { + ID string + Algorithm string + SigningKey crypto.PrivateKey +} + +type serializedPool struct { + Authorities []*serializedAuthority +} + +type serializedAuthority struct { + ID string + Algorithm string + SigningKeyPKCS8 []byte +} + +// Marshal serializes a Pool to JSON. +func Marshal(pool *Pool) ([]byte, error) { + wire := &serializedPool{} + + for _, authority := range pool.Authorities { + authorityWire := &serializedAuthority{} + authorityWire.ID = authority.ID + authorityWire.Algorithm = authority.Algorithm + + signingKeyPKCS8, err := x509.MarshalPKCS8PrivateKey(authority.SigningKey) + if err != nil { + return nil, fmt.Errorf("while serializing signing key to PKCS#8: %w", err) + } + authorityWire.SigningKeyPKCS8 = signingKeyPKCS8 + + wire.Authorities = append(wire.Authorities, authorityWire) + } + + wireBytes, err := json.Marshal(wire) + if err != nil { + return nil, fmt.Errorf("while marshaling to JSON: %w", err) + } + + return wireBytes, nil +} + +// Unmarshal loads a Pool from JSON. +func Unmarshal(wireBytes []byte) (*Pool, error) { + wire := &serializedPool{} + + if err := json.Unmarshal(wireBytes, wire); err != nil { + return nil, fmt.Errorf("while unmarshaling JSON: %w", err) + } + + pool := &Pool{} + for _, wireAuthority := range wire.Authorities { + authority := &Authority{ + ID: wireAuthority.ID, + Algorithm: wireAuthority.Algorithm, + } + + signingKey, err := x509.ParsePKCS8PrivateKey(wireAuthority.SigningKeyPKCS8) + if err != nil { + return nil, fmt.Errorf("while parsing signing key: %w", err) + } + authority.SigningKey = signingKey + + pool.Authorities = append(pool.Authorities, authority) + } + + return pool, nil +} + +// GenerateECDSAP256Authority generates an ECDSA P256 JWT signing key. +func GenerateECDSAP256Authority(id string) (*Authority, error) { + privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, fmt.Errorf("while generating key: %w", err) + } + + return &Authority{ + ID: id, + Algorithm: "ES256", + SigningKey: privKey, + }, nil +} diff --git a/internal/memorypullcache/memorypullcache.go b/internal/memorypullcache/memorypullcache.go new file mode 100644 index 000000000..1d6b07dd8 --- /dev/null +++ b/internal/memorypullcache/memorypullcache.go @@ -0,0 +1,217 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memorypullcache + +import ( + "bytes" + "context" + "fmt" + "io" + "log/slog" + "net" + "runtime" + "strings" + + "cloud.google.com/go/storage" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/mutate" + "github.com/google/go-containerregistry/pkg/v1/remote" + "k8s.io/utils/lru" +) + +type MemoryPullCache struct { + gcsClient *storage.Client + + gcpAuthenticator authn.Authenticator + + localhostRegistryReplacement string + + // Map from hexadecimal sha256 hash of image to byte contents of composed + // tarball + cache *lru.Cache +} + +func NewMemoryPullCache(ctx context.Context, gcpAuthenticator authn.Authenticator, localhostRegistryReplacement string) (*MemoryPullCache, error) { + c := &MemoryPullCache{ + // TODO: Need a smarter cache with bounds on total consumed size, not + // just number of entries. Potentially also try to share the cache + // across ateoms on the same machine. + // + // It would have to be a directory with files named after the sha256 + // hash. The benefit would be that a read might be found in the + // filesystem cache, or perhaps the folder could be on SSD. + // + // From the perspective of stable operation, without hidden kernel + // caches that could fill up or have weird behavior, it might be better + // to just have two levels. Store some images in ateom memory, and the + // rest are kept in a shared GCS cache. + cache: lru.New(256), + localhostRegistryReplacement: localhostRegistryReplacement, + } + + c.gcpAuthenticator = gcpAuthenticator + + return c, nil +} + +func (c *MemoryPullCache) Fetch(ctx context.Context, ref string) (io.ReadCloser, error) { + // when running in kind we need to rewrite the registry endpoint similar to the + // containerd mirror config used in https://kind.sigs.k8s.io/docs/user/local-registry/ + // for now we have simple opt-in support to rewrite local registries + rewritten := false + if c.localhostRegistryReplacement != "" { + newRef := c.rewriteLocalRegistry(ref) + if newRef != ref { + ref = newRef + rewritten = true + } + } + var nameOpts []name.Option + // match docker behavior, permit http image pulls for local registries + // this avoids needing to distribute TLS certs all around for local development + if rewritten || isLocalRegistry(ref) { + nameOpts = append(nameOpts, name.Insecure) + } + + parsedRef, err := name.ParseReference(ref, nameOpts...) + if err != nil { + return nil, fmt.Errorf("while parsing reference: %w", err) + } + + // If the image ref included a digest, check for a hit in the pull cache. + requestedDigest, digestWasIncluded := parsedRef.(name.Digest) + if digestWasIncluded { + slog.InfoContext( + ctx, + "Ref includes digest, checking for cache hit", + slog.String("ref", ref), + slog.String("digest", requestedDigest.DigestStr()), + ) + + if vAny, ok := c.cache.Get(requestedDigest.DigestStr()); ok { + slog.InfoContext( + ctx, + "Cache hit", + slog.String("ref", ref), + slog.String("digest", requestedDigest.DigestStr()), + ) + return io.NopCloser(bytes.NewReader(vAny.([]byte))), nil + } + } + + slog.InfoContext( + ctx, + "Cache miss", + slog.String("ref", ref), + ) + + // If we didn't have a cache hit, we are on the slow path of pulling the + // image from the registry. This is a chatty process, with multiple round + // trips to the registry. + + var remoteOptions []remote.Option + remoteOptions = append(remoteOptions, remote.WithPlatform(v1.Platform{ + Architecture: runtime.GOARCH, + OS: "linux", + })) + + registry := parsedRef.Context().Registry.RegistryStr() + if registry == "gcr.io" || strings.HasSuffix(registry, ".gcr.io") || registry == "pkg.dev" || strings.HasSuffix(registry, ".pkg.dev") { + if c.gcpAuthenticator != nil { + remoteOptions = append(remoteOptions, remote.WithAuth(c.gcpAuthenticator)) + } + } + + img, err := remote.Image(parsedRef, remoteOptions...) + if err != nil { + return nil, fmt.Errorf("in remote.Image: %w", err) + } + + size, err := img.Size() + if err != nil { + return nil, fmt.Errorf("in img.Size(): %w", err) + } + if size > 100*1024*1024 { + slog.InfoContext(ctx, + "Image is too large to cache", + slog.String("ref", ref), + slog.Int64("size", size), + ) + return mutate.Extract(img), err + } + + tarData := mutate.Extract(img) + defer tarData.Close() + + memData, err := io.ReadAll(tarData) + if err != nil { + return nil, fmt.Errorf("while reading image: %w", err) + } + + if digestWasIncluded { + // If the user requested multi-arch image, the digest they request will + // not be the same as the digest of the image we actually downloaded + // from the registry. We need to place the cache entry under the digest + // they requested. + c.cache.Add(requestedDigest.DigestStr(), memData) + slog.InfoContext( + ctx, + "Populated image cache", + slog.String("ref", ref), + slog.String("digest", requestedDigest.DigestStr()), + ) + } + + return io.NopCloser(bytes.NewReader(memData)), nil +} + +func registryHost(ref string) string { + parts := strings.SplitN(ref, "/", 2) + reg, err := name.NewRegistry(parts[0], name.Insecure) + if err != nil { + return "" + } + hostPart := reg.Name() + if h, _, err := net.SplitHostPort(hostPart); err == nil { + return h + } + return hostPart +} + +func isLocalhostOrLoopback(host string) bool { + if host == "localhost" { + return true + } + if ip := net.ParseIP(host); ip != nil && ip.IsLoopback() { + return true + } + return false +} + +func isLocalRegistry(ref string) bool { + // by default docker permits localhost and 127.0.0.0/8 + // we also permit IPv6 loopback here + return isLocalhostOrLoopback(registryHost(ref)) +} + +func (c *MemoryPullCache) rewriteLocalRegistry(ref string) string { + if isLocalRegistry(ref) { + parts := strings.SplitN(ref, "/", 2) + return c.localhostRegistryReplacement + "/" + parts[1] + } + return ref +} diff --git a/internal/memorypullcache/memorypullcache_test.go b/internal/memorypullcache/memorypullcache_test.go new file mode 100644 index 000000000..781120955 --- /dev/null +++ b/internal/memorypullcache/memorypullcache_test.go @@ -0,0 +1,84 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package memorypullcache + +import ( + "testing" +) + +func TestIsLocalRegistry(t *testing.T) { + tests := []struct { + ref string + want bool + }{ + {ref: "localhost/foo", want: true}, + {ref: "localhost:5001/foo", want: true}, + {ref: "127.0.0.1/foo", want: true}, + {ref: "127.0.0.1:5001/foo", want: true}, + {ref: "127.0.0.2/foo", want: true}, + {ref: "127.0.0.2:8080/foo", want: true}, + {ref: "kind-registry/foo", want: false}, + {ref: "kind-registry:5000/foo", want: false}, + {ref: "my-registry.local/foo", want: false}, + {ref: "my-registry.local:8080/foo", want: false}, + {ref: "gcr.io/foo", want: false}, + {ref: "example.com/foo", want: false}, + {ref: "foo", want: false}, + {ref: "", want: false}, + } + + for _, tt := range tests { + t.Run(tt.ref, func(t *testing.T) { + got := isLocalRegistry(tt.ref) + if got != tt.want { + t.Errorf("isLocalRegistry(%q) = %v; want %v", tt.ref, got, tt.want) + } + }) + } +} + +func TestRewriteLocalRegistry(t *testing.T) { + c := &MemoryPullCache{ + localhostRegistryReplacement: "kind-registry:5000", + } + + tests := []struct { + ref string + want string + }{ + {ref: "localhost/foo", want: "kind-registry:5000/foo"}, + {ref: "localhost:5001/foo", want: "kind-registry:5000/foo"}, + {ref: "localhost:8080/foo", want: "kind-registry:5000/foo"}, + {ref: "127.0.0.1/foo", want: "kind-registry:5000/foo"}, + {ref: "127.0.0.1:3000/foo", want: "kind-registry:5000/foo"}, + {ref: "127.0.0.2/foo", want: "kind-registry:5000/foo"}, + {ref: "127.0.0.2:8080/foo", want: "kind-registry:5000/foo"}, + {ref: "kind-registry/foo", want: "kind-registry/foo"}, + {ref: "kind-registry:5000/foo", want: "kind-registry:5000/foo"}, + {ref: "my-registry.local/foo", want: "my-registry.local/foo"}, + {ref: "gcr.io/foo", want: "gcr.io/foo"}, + {ref: "foo", want: "foo"}, + {ref: "", want: ""}, + } + + for _, tt := range tests { + t.Run(tt.ref, func(t *testing.T) { + got := c.rewriteLocalRegistry(tt.ref) + if got != tt.want { + t.Errorf("rewriteLocalRegistry(%q) = %q; want %q", tt.ref, got, tt.want) + } + }) + } +} diff --git a/internal/podidentitysigner/podidentitysigner.go b/internal/podidentitysigner/podidentitysigner.go new file mode 100644 index 000000000..bae92a2c6 --- /dev/null +++ b/internal/podidentitysigner/podidentitysigner.go @@ -0,0 +1,176 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package podidentitysigner + +import ( + "bytes" + "context" + "crypto" + "crypto/rand" + "crypto/x509" + "encoding/pem" + "fmt" + "net/url" + "path" + "time" + + "github.com/agent-substrate/substrate/internal/localca" + "github.com/agent-substrate/substrate/internal/signercontroller" + certsv1beta1 "k8s.io/api/certificates/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/utils/clock" + "k8s.io/utils/ptr" +) + +const Name = "podidentity.podcert.ate.dev/identity" +const CTBPrefix = "podidentity.podcert.ate.dev:identity:" + +type Impl struct { + kc kubernetes.Interface + caPool *localca.Pool + + clock clock.PassiveClock +} + +func NewImpl(kc kubernetes.Interface, caPool *localca.Pool, clock clock.PassiveClock) *Impl { + return &Impl{ + kc: kc, + caPool: caPool, + clock: clock, + } +} + +var _ signercontroller.SignerImpl = (*Impl)(nil) + +func (h *Impl) SignerName() string { + return Name +} + +func (h *Impl) DesiredClusterTrustBundles() []*certsv1beta1.ClusterTrustBundle { + name := CTBPrefix + "primary-bundle" + + wantTrustBundle := bytes.Buffer{} + for _, ca := range h.caPool.CAs { + block := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: ca.RootCertificate.Raw, + }) + _, _ = wantTrustBundle.Write(block) + } + + wantCTB := &certsv1beta1.ClusterTrustBundle{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "podcert.ate.dev/canarying": "live", + }, + }, + Spec: certsv1beta1.ClusterTrustBundleSpec{ + SignerName: Name, + TrustBundle: wantTrustBundle.String(), + }, + } + + return []*certsv1beta1.ClusterTrustBundle{ + wantCTB, + } +} + +func (h *Impl) MakeCert(ctx context.Context, pcr *certsv1beta1.PodCertificateRequest) error { + // Fetch the pod to get its ServiceAccount + pod, err := h.kc.CoreV1().Pods(pcr.ObjectMeta.Namespace).Get(ctx, pcr.Spec.PodName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("while getting pod %s/%s: %w", pcr.ObjectMeta.Namespace, pcr.Spec.PodName, err) + } + + if pod.ObjectMeta.UID != pcr.Spec.PodUID { + return fmt.Errorf("pod UID mismatch: expected %s, got %s", pcr.Spec.PodUID, pod.ObjectMeta.UID) + } + + var subjectPublicKey crypto.PublicKey + subjectPublicKey, err = x509.ParsePKIXPublicKey(pcr.Spec.PKIXPublicKey) + if err != nil { + return fmt.Errorf("while parsing PKIX public key: %w", err) + } + + lifetime := 24 * time.Hour + requestedLifetime := time.Duration(*pcr.Spec.MaxExpirationSeconds) * time.Second + if requestedLifetime < lifetime { + lifetime = requestedLifetime + } + + notBefore := h.clock.Now().Add(-2 * time.Minute) + notAfter := notBefore.Add(lifetime) + beginRefreshAt := notAfter.Add(-30 * time.Minute) + + spiffeURI := &url.URL{ + Scheme: "spiffe", + Host: "cluster.local", + Path: path.Join("ns", pcr.ObjectMeta.Namespace, "sa", pcr.Spec.ServiceAccountName), + } + + template := &x509.Certificate{ + BasicConstraintsValid: true, + NotBefore: notBefore, + NotAfter: notAfter, + URIs: []*url.URL{spiffeURI}, + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + } + + subjectCertDER, err := x509.CreateCertificate(rand.Reader, template, h.caPool.CAs[0].RootCertificate, subjectPublicKey, h.caPool.CAs[0].SigningKey) + if err != nil { + return fmt.Errorf("while signing subject cert: %w", err) + } + + chainDER := [][]byte{subjectCertDER} + for _, intermed := range h.caPool.CAs[0].IntermediateCertificates { + chainDER = append(chainDER, intermed.Raw) + } + + chainPEM := &bytes.Buffer{} + for _, certDER := range chainDER { + err = pem.Encode(chainPEM, &pem.Block{ + Type: "CERTIFICATE", + Bytes: certDER, + }) + if err != nil { + return fmt.Errorf("while encoding certificate to PEM: %w", err) + } + } + + pcr = pcr.DeepCopy() + pcr.Status.Conditions = []metav1.Condition{ + { + Type: certsv1beta1.PodCertificateRequestConditionTypeIssued, + Status: metav1.ConditionTrue, + Reason: "Reason", + Message: "Issued", + LastTransitionTime: metav1.NewTime(h.clock.Now()), + }, + } + pcr.Status.CertificateChain = chainPEM.String() + pcr.Status.NotBefore = ptr.To(metav1.NewTime(notBefore)) + pcr.Status.BeginRefreshAt = ptr.To(metav1.NewTime(beginRefreshAt)) + pcr.Status.NotAfter = ptr.To(metav1.NewTime(notAfter)) + + _, err = h.kc.CertificatesV1beta1().PodCertificateRequests(pcr.ObjectMeta.Namespace).UpdateStatus(ctx, pcr, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("while updating PodCertificateRequest: %w", err) + } + + return nil +} diff --git a/internal/rendezvous/rendezvous.go b/internal/rendezvous/rendezvous.go new file mode 100644 index 000000000..4caf1f783 --- /dev/null +++ b/internal/rendezvous/rendezvous.go @@ -0,0 +1,281 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package rendezvous uses rendezvous hashing to help multiple controller replicas +// agree on which replica should handle an item. The assignment is not atomic, +// so the controllers' actions need to be safe even if multiple replicas attempt +// to process the same item simultaneously. However, in the steady state, where +// all replicas agree on the set of all healthy replicas. +package rendezvous + +import ( + "context" + "errors" + "fmt" + "hash/fnv" + "log/slog" + "time" + + coordinationv1 "k8s.io/api/coordination/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + coordinationinformersv1 "k8s.io/client-go/informers/coordination/v1" + "k8s.io/client-go/kubernetes" + coordinationlistersv1 "k8s.io/client-go/listers/coordination/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/utils/clock" + "k8s.io/utils/ptr" +) + +const labelKey = "rendezvous.ate.dev/application" + +var ( + leaseDuration = 15 * time.Second + leaseRenewalPeriod = 10 * time.Second +) + +var ErrNotAssigned = errors.New("item not assigned to this replica") + +// Hasher is a rendezvous hashing implementation built on top of Kubernetes +// leases. +// +// Use Hasher when: +// +// * You have multiple replicas of your application. +// +// * You want to partition work items efficiently between them, minimizing +// redundant work. +// +// * You can tolerate multiple replicas working on the same item at the same +// time. +// +// As opposed to leader election, rendezvous hashing lets us spread the +// controller's work across all live replicas of the controller. As controller +// replicas spin up and down, work items will be gracefully rebalanced among the +// live replicas. In general, if there are m items, and n replicas running, m/n +// items will be rebalanced to the remaining live replicas, with most items +// remaining at the same replica. +// +// Internally, Hasher writes a heartbeat to a specific Lease object, and scans +// for other Lease objects created by other replicas of your application. If +// the lease has been renewed recently, the corresponding replica is considered +// live, otherwise it is considered dead and ignored. Hasher will attempt to +// clean up owned Lease objects that seem to have been dead for longer than an +// hour. It is possible for replicas to briefly disagree about the set of live +// replicas during membership changes, which may lead to affected items being +// ignored for up to one Lease timeout period. This is no worse than the +// timeout behavior of Lease-based leader election. +// +// To use Hasher, you provide information about the Lease objects that will be +// created and queried: namespace and label selector. You also provide the ID +// of the current replica, which is used as both the name of the replica's Lease +// and the identity of the owner of the lease. It's fine to use a random UUID +// for your ID, but you can get greater stability across restarts by choosing a +// more persistent identifier. +// +// There's no reason to create more than one Hasher instance per binary. +// +// Hasher is based on the FNV-1a 64-bit variant. +type Hasher struct { + kc kubernetes.Interface + + leaseNamespace string + applicationName string + replicaName string + replicaUID types.UID + + leaseInformer cache.SharedIndexInformer + + clock clock.Clock +} + +// New returns a new Hasher. +func New(kc kubernetes.Interface, namespace, applicationName, replicaName string, replicaUID types.UID, clock clock.Clock) *Hasher { + leaseLabelSelector := labels.SelectorFromSet(labels.Set{ + labelKey: applicationName, + }) + + leaseInformer := coordinationinformersv1.NewFilteredLeaseInformer( + kc, + namespace, + 0, + cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, + func(opts *metav1.ListOptions) { + opts.LabelSelector = leaseLabelSelector.String() + }, + ) + + return &Hasher{ + kc: kc, + leaseNamespace: namespace, + replicaName: replicaName, + replicaUID: replicaUID, + applicationName: applicationName, + + leaseInformer: leaseInformer, + + clock: clock, + } +} + +// Run starts the Hasher, blocking the current goroutine until ctx is done. +func (h *Hasher) Run(ctx context.Context) { + go h.leaseInformer.Run(ctx.Done()) + if !cache.WaitForCacheSync(ctx.Done(), h.leaseInformer.HasSynced) { + return + } + go wait.UntilWithContext(ctx, h.runOnce, leaseRenewalPeriod) + <-ctx.Done() +} + +func (h *Hasher) runOnce(ctx context.Context) { + if err := h.ensureLease(ctx); err != nil { + slog.ErrorContext(ctx, "Error while ensuring lease", slog.String("err", err.Error())) + } +} + +func (h *Hasher) ensureLease(ctx context.Context) error { + now := h.clock.Now() + + desiredLease := &coordinationv1.Lease{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: h.leaseNamespace, + Name: h.replicaName, + Labels: map[string]string{ + labelKey: h.applicationName, + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "v1", + Kind: "Pod", + Name: h.replicaName, + UID: h.replicaUID, + Controller: ptr.To(true), + }, + }, + }, + Spec: coordinationv1.LeaseSpec{ + HolderIdentity: &h.replicaName, + LeaseDurationSeconds: ptr.To(int32(int64(leaseDuration) / 1_000_000_000)), + AcquireTime: ptr.To(metav1.NewMicroTime(now)), + RenewTime: ptr.To(metav1.NewMicroTime(now)), + LeaseTransitions: ptr.To[int32](1), + }, + } + + lease, err := h.kc.CoordinationV1().Leases(h.leaseNamespace).Get(ctx, h.replicaName, metav1.GetOptions{}) + if k8serrors.IsNotFound(err) { + _, err = h.kc.CoordinationV1().Leases(h.leaseNamespace).Create(ctx, desiredLease, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("while creating lease: %w", err) + } + return nil + } else if err != nil { + return fmt.Errorf("while getting lease: %w", err) + } + + lease.ObjectMeta.Labels = desiredLease.Labels + lease.ObjectMeta.OwnerReferences = desiredLease.OwnerReferences + lease.Spec.HolderIdentity = desiredLease.Spec.HolderIdentity + lease.Spec.LeaseDurationSeconds = desiredLease.Spec.LeaseDurationSeconds + lease.Spec.RenewTime = desiredLease.Spec.RenewTime + + _, err = h.kc.CoordinationV1().Leases(h.leaseNamespace).Update(ctx, lease, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("while updating lease: %w", err) + } + + return nil +} + +// AssignedToThisReplica uses rendezvous hashing to decide if the given item is +// assigned to the current replica. +// +// Item needs to be a stable identifier for the work item, like namespace/name +// or UID. You don't need to treat the keys to make them uniform; that is +// handled by the rendezvous hashing implementation. +// +// To avoid leaking work items, you should continue to recheck items that are +// currently not assigned to this replica until they are finished, just in case, +// they get reassigned to this replica. For example, when processing +// PodCertificateRequests, if the PCR is not currently assigned to this replica, +// add it back to the work queue with backoff. Once the PCR is issued, it can +// be removed from the workqueue. +func (h *Hasher) AssignedToThisReplica(ctx context.Context, item string) bool { + now := h.clock.Now() + + // List all Leases known to the informer --- we filtered based on our label + // selector when defining the informer. + leases, err := coordinationlistersv1.NewLeaseLister(h.leaseInformer.GetIndexer()).Leases(h.leaseNamespace).List(labels.Everything()) + if err != nil { + slog.ErrorContext(ctx, "Error while listing all leases in informer", slog.String("err", err.Error())) + return false + } + + liveReplicas := make([]string, 0, len(leases)) + for _, lease := range leases { + var leaseDuration time.Duration + if lease.Spec.LeaseDurationSeconds != nil { + leaseDuration = time.Duration(*lease.Spec.LeaseDurationSeconds) * time.Second + } + + // If the replica hasn't checked in by the deadline, consider it dead. + deadline := lease.Spec.RenewTime.Time.Add(leaseDuration) + if now.After(deadline) { + continue + } + + if lease.Spec.HolderIdentity == nil { + continue + } + + liveReplicas = append(liveReplicas, *lease.Spec.HolderIdentity) + } + + return Hash(item, liveReplicas) == h.replicaName +} + +func Hash(item string, replicas []string) string { + // Rendezvous hashing: hash the item key with each replica key, and consider + // the item assigned to the replica with the maximum hash value. + maxWeight := uint64(0) + maxReplica := "" + for _, replica := range replicas { + weight := fnvhash(item + replica) + + if maxReplica == "" { + maxWeight = weight + maxReplica = replica + continue + } + + // Tiebreak consistently if two replicas have the same weight + if weight > maxWeight || (weight == maxWeight && replica < maxReplica) { + maxWeight = weight + maxReplica = replica + continue + } + } + + return maxReplica +} + +func fnvhash(key string) uint64 { + hasher := fnv.New64() + _, _ = hasher.Write([]byte(key)) + return hasher.Sum64() +} diff --git a/internal/resources/actor.go b/internal/resources/actor.go new file mode 100644 index 000000000..365660452 --- /dev/null +++ b/internal/resources/actor.go @@ -0,0 +1,47 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resources + +import ( + "fmt" + "regexp" +) + +const ( + // ActorIDRegexPattern is the regular expression pattern for matching valid actor IDs. + ActorIDRegexPattern = `[a-z0-9]([-a-z0-9]*[a-z0-9])?` + // ActorDNSSuffix is suffix to the DNS name for direct access to Actor + // ".actors.resources.substrate.ate.dev." + ActorDNSSuffix = "actors.resources.substrate.ate.dev" +) + +var actorIDRegex = regexp.MustCompile("^" + ActorIDRegexPattern + "$") + +// ValidateActorID validates whether the provided actor ID is valid or not. +// Actor IDs must be valid DNS-1123 labels. +// +// 1. Must be between 1 and 63 characters in length. +// 2. Must start with a lower-case alphanumeric character (a-z, 0-9). +// 3. Must contain only lower-case alphanumeric characters and hyphens (a-z, 0-9, -). +// 4. Must end with a lower-case alphanumeric character (cannot end with a hyphen). +func ValidateActorID(id string) error { + if len(id) > 63 { + return fmt.Errorf("invalid actor_id: must be no more than 63 characters") + } + if !actorIDRegex.MatchString(id) { + return fmt.Errorf("invalid actor_id: must start and end with a lower case alphanumeric character, and consist only of lower case alphanumeric characters or '-'") + } + return nil +} diff --git a/internal/resources/actor_test.go b/internal/resources/actor_test.go new file mode 100644 index 000000000..b1d0b2cd9 --- /dev/null +++ b/internal/resources/actor_test.go @@ -0,0 +1,45 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resources + +import ( + "strings" + "testing" +) + +func TestValidateActorID(t *testing.T) { + tests := []struct { + name string + id string + wantErr bool + }{ + {"valid lowercase", "my-actor-1", false}, + {"valid single char", "a", false}, + {"missing id", "", true}, + {"invalid uppercase", "My-Actor", true}, + {"invalid start hyphen", "-actor", true}, + {"valid start number", "1actor", false}, + {"invalid end hyphen", "actor-", true}, + {"invalid special chars", "actor@1", true}, + {"invalid length", strings.Repeat("a", 64), true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateActorID(tt.id); (err != nil) != tt.wantErr { + t.Errorf("ValidateActorID() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/servicednssigner/servicednssigner.go b/internal/servicednssigner/servicednssigner.go new file mode 100644 index 000000000..8021f0e5a --- /dev/null +++ b/internal/servicednssigner/servicednssigner.go @@ -0,0 +1,213 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package servicednssigner + +import ( + "bytes" + "context" + "crypto" + "crypto/rand" + "crypto/x509" + "encoding/pem" + "fmt" + "time" + + "github.com/agent-substrate/substrate/internal/localca" + "github.com/agent-substrate/substrate/internal/signercontroller" + certsv1beta1 "k8s.io/api/certificates/v1beta1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/utils/clock" + "k8s.io/utils/ptr" +) + +const Name = "servicedns.podcert.ate.dev/identity" + +const CTBPrefix = "servicedns.podcert.ate.dev:identity:" + +type Impl struct { + kc kubernetes.Interface + caPool *localca.Pool + + clock clock.PassiveClock +} + +func NewImpl(kc kubernetes.Interface, caPool *localca.Pool, clock clock.PassiveClock) *Impl { + return &Impl{ + kc: kc, + caPool: caPool, + clock: clock, + } +} + +var _ signercontroller.SignerImpl = (*Impl)(nil) + +func (h *Impl) SignerName() string { + return Name +} + +func (h *Impl) DesiredClusterTrustBundles() []*certsv1beta1.ClusterTrustBundle { + name := CTBPrefix + "primary-bundle" + + wantTrustBundle := bytes.Buffer{} + for _, ca := range h.caPool.CAs { + block := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: ca.RootCertificate.Raw, + }) + _, _ = wantTrustBundle.Write(block) + } + + wantCTB := &certsv1beta1.ClusterTrustBundle{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "podcert.ate.dev/canarying": "live", + }, + }, + Spec: certsv1beta1.ClusterTrustBundleSpec{ + SignerName: Name, + TrustBundle: wantTrustBundle.String(), + }, + } + + return []*certsv1beta1.ClusterTrustBundle{ + wantCTB, + } +} + +func (h *Impl) MakeCert(ctx context.Context, pcr *certsv1beta1.PodCertificateRequest) error { + // TODO: Switch from live reads to indexer + + // If our signer had a policy about which pods are allowed to request + // certificates, it would be implemented here. + + svcs, err := h.kc.CoreV1().Services(pcr.ObjectMeta.Namespace).List(ctx, metav1.ListOptions{}) + if err != nil { + return fmt.Errorf("while listing services: %w", err) + } + + // TODO: Looping over every service isn't great. Maintain an index of pod + // to covering services. + + dnsNames := []string{} + for _, svc := range svcs.Items { + switch svc.Spec.Type { + case corev1.ServiceTypeClusterIP, corev1.ServiceTypeNodePort, corev1.ServiceTypeLoadBalancer: + // ok + default: + // This service type doesn't select pods using a label selector. + continue + } + + // Find the set of pods that the service selects. + matchedPods, err := h.kc.CoreV1().Pods(pcr.ObjectMeta.Namespace).List(ctx, metav1.ListOptions{ + LabelSelector: metav1.FormatLabelSelector(&metav1.LabelSelector{MatchLabels: svc.Spec.Selector}), + }) + if err != nil { + return fmt.Errorf("while selecting pods for service %q: %w", pcr.ObjectMeta.Namespace+"/"+svc.ObjectMeta.Name, err) + } + + for _, matchedPod := range matchedPods.Items { + if matchedPod.ObjectMeta.Name == pcr.Spec.PodName && matchedPod.ObjectMeta.UID == pcr.Spec.PodUID { + // TODO: I'm making some assumptions about the DNS names that + // resolve to a given Service. I know at least one + // configuration that I suspect doesn't match these assumptions + // --- GKE with VPC-scoped Cloud DNS [1]. + // + // [1] https://cloud.google.com/kubernetes-engine/docs/how-to/cloud-dns#vpc_scope_dns + name := fmt.Sprintf("%s.%s.svc", svc.ObjectMeta.Name, svc.ObjectMeta.Namespace) + dnsNames = append(dnsNames, name) + } + } + } + + // TODO: Encode the OIDC issuer of the cluster into the certificate. + + // In Kubernetes 1.35, Kubelet sets PKIXPublicKey. In 1.36, Kubelet sets + // UnverifiedPKCS10Request. + var subjectPublicKey crypto.PublicKey + subjectPublicKey, err = x509.ParsePKIXPublicKey(pcr.Spec.PKIXPublicKey) + if err != nil { + return fmt.Errorf("while parsing PKIX public key: %w", err) + } + + // If our signer had an opinion on which key types were allowable, it would + // check subjectPublicKey, and deny the PCR with a SuggestedKeyType + // condition on it. + + lifetime := 24 * time.Hour + requestedLifetime := time.Duration(*pcr.Spec.MaxExpirationSeconds) * time.Second + if requestedLifetime < lifetime { + lifetime = requestedLifetime + } + + notBefore := h.clock.Now().Add(-2 * time.Minute) + notAfter := notBefore.Add(lifetime) + beginRefreshAt := notAfter.Add(-30 * time.Minute) + + template := &x509.Certificate{ + BasicConstraintsValid: true, + NotBefore: notBefore, + NotAfter: notAfter, + DNSNames: dnsNames, + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + } + + subjectCertDER, err := x509.CreateCertificate(rand.Reader, template, h.caPool.CAs[0].RootCertificate, subjectPublicKey, h.caPool.CAs[0].SigningKey) + if err != nil { + return fmt.Errorf("while signing subject cert: %w", err) + } + + chainDER := [][]byte{subjectCertDER} + for _, intermed := range h.caPool.CAs[0].IntermediateCertificates { + chainDER = append(chainDER, intermed.Raw) + } + + chainPEM := &bytes.Buffer{} + for _, certDER := range chainDER { + err = pem.Encode(chainPEM, &pem.Block{ + Type: "CERTIFICATE", + Bytes: certDER, + }) + if err != nil { + return fmt.Errorf("while encoding certificate to PEM: %w", err) + } + } + + pcr = pcr.DeepCopy() + pcr.Status.Conditions = []metav1.Condition{ + { + Type: certsv1beta1.PodCertificateRequestConditionTypeIssued, + Status: metav1.ConditionTrue, + Reason: "Reason", + Message: "Issued", + LastTransitionTime: metav1.NewTime(h.clock.Now()), + }, + } + pcr.Status.CertificateChain = chainPEM.String() + pcr.Status.NotBefore = ptr.To(metav1.NewTime(notBefore)) + pcr.Status.BeginRefreshAt = ptr.To(metav1.NewTime(beginRefreshAt)) + pcr.Status.NotAfter = ptr.To(metav1.NewTime(notAfter)) + + _, err = h.kc.CertificatesV1beta1().PodCertificateRequests(pcr.ObjectMeta.Namespace).UpdateStatus(ctx, pcr, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("while updating PodCertificateRequest: %w", err) + } + + return nil +} diff --git a/internal/sessionidjwt/sessionidjwt.go b/internal/sessionidjwt/sessionidjwt.go new file mode 100644 index 000000000..138af4bd4 --- /dev/null +++ b/internal/sessionidjwt/sessionidjwt.go @@ -0,0 +1,170 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sessionidjwt + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "encoding/base64" + "encoding/json" + "fmt" + "hash" + "time" +) + +type Claims struct { + // Claims from RFC7519 + Issuer string + Subject string + Audiences []string + Expiration time.Time + NotBefore time.Time + IssuedAt time.Time + JTI string + + // Claims from ADK's session model + Substrate SubstrateClaims +} + +type SubstrateClaims struct { + AppID string + UserID string + SessionID string +} + +type wireHeader struct { + Type string `json:"typ,omitempty"` + Algorithm string `json:"alg,omitempty"` + KeyID string `json:"kid,omitempty"` +} + +type WireClaims struct { + // Claims from RFC7519 + Issuer string `json:"iss,omitempty"` + Subject string `json:"sub,omitempty"` + Audiences json.RawMessage `json:"aud,omitempty"` + Expiration float64 `json:"exp,omitempty"` + NotBefore float64 `json:"nbf,omitempty"` + IssuedAt float64 `json:"iat,omitempty"` + JTI string `json:"jti,omitempty"` + + // Claims from ADK's session model. + Substrate WireSubstrateClaims `json:"ate.dev,omitempty"` +} + +type WireSubstrateClaims struct { + AppID string `json:"appID,omitempty"` + UserID string `json:"userID,omitempty"` + SessionID string `json:"sessionID,omitempty"` +} + +func ClaimsToWire(claims *Claims) (*WireClaims, error) { + rawAudiences, err := json.Marshal(claims.Audiences) + if err != nil { + return nil, fmt.Errorf("while marshaling audience: %w", err) + } + + wire := &WireClaims{ + Issuer: claims.Issuer, + Subject: claims.Subject, + Audiences: rawAudiences, + Expiration: float64(claims.Expiration.Unix()), + NotBefore: float64(claims.NotBefore.Unix()), + IssuedAt: float64(claims.IssuedAt.Unix()), + JTI: claims.JTI, + Substrate: WireSubstrateClaims{ + claims.Substrate.AppID, + claims.Substrate.UserID, + claims.Substrate.SessionID, + }, + } + + return wire, nil +} + +// Sign +func Sign(wireClaims *WireClaims, signingKey crypto.PrivateKey, algorithm, keyID string) (string, error) { + payloadBytes, err := json.Marshal(wireClaims) + if err != nil { + return "", fmt.Errorf("while marshaling payload: %w", err) + } + payloadB64 := base64.RawURLEncoding.EncodeToString(payloadBytes) + + rawHeader := wireHeader{ + Algorithm: algorithm, + KeyID: keyID, + } + headerBytes, err := json.Marshal(rawHeader) + if err != nil { + return "", fmt.Errorf("while marshaling header: %w", err) + } + headerB64 := base64.RawURLEncoding.EncodeToString(headerBytes) + + toBeSigned := headerB64 + "." + payloadB64 + + var sigBytes []byte + switch algorithm { + case "RS256": + rsaKey := signingKey.(*rsa.PrivateKey) + toBeSignedDigest := hashBytes(crypto.SHA256.New(), []byte(toBeSigned)) + sigBytes, err = rsa.SignPKCS1v15(rand.Reader, rsaKey, crypto.SHA256, toBeSignedDigest) + if err != nil { + return "", fmt.Errorf("while performing RSA PKCS1v15 signature: %w", err) + } + case "RS384": + rsaKey := signingKey.(*rsa.PrivateKey) + toBeSignedDigest := hashBytes(crypto.SHA384.New(), []byte(toBeSigned)) + sigBytes, err = rsa.SignPKCS1v15(rand.Reader, rsaKey, crypto.SHA384, toBeSignedDigest) + if err != nil { + return "", fmt.Errorf("while performing RSA PKCS1v15 signature: %w", err) + } + case "RS512": + rsaKey := signingKey.(*rsa.PrivateKey) + toBeSignedDigest := hashBytes(crypto.SHA512.New(), []byte(toBeSigned)) + sigBytes, err = rsa.SignPKCS1v15(rand.Reader, rsaKey, crypto.SHA512, toBeSignedDigest) + if err != nil { + return "", fmt.Errorf("while performing RSA PKCS1v15 signature: %w", err) + } + case "ES256": + // JOSE ES256 defined at https://datatracker.ietf.org/doc/rfc7518/ section 3.4 + ecdsaKey := signingKey.(*ecdsa.PrivateKey) + if ecdsaKey.Curve != elliptic.P256() { + return "", fmt.Errorf("ES256 requires a P256 key") + } + toBeSignedDigest := hashBytes(crypto.SHA256.New(), []byte(toBeSigned)) + r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, toBeSignedDigest) + if err != nil { + return "", fmt.Errorf("while performing ecdsa signature: %w", err) + } + sigBytes = make([]byte, 2*32) + r.FillBytes(sigBytes[:32]) + s.FillBytes(sigBytes[32:]) + default: + return "", fmt.Errorf("unimplemented algorithm %q", algorithm) + } + + sigB64 := base64.RawURLEncoding.EncodeToString(sigBytes) + + return toBeSigned + "." + sigB64, nil +} + +func hashBytes(hasher hash.Hash, bytes []byte) []byte { + hasher.Write(bytes) + hash := hasher.Sum(nil) + return hash[:] +} diff --git a/internal/signercontroller/signercontroller.go b/internal/signercontroller/signercontroller.go new file mode 100644 index 000000000..52e9e857f --- /dev/null +++ b/internal/signercontroller/signercontroller.go @@ -0,0 +1,249 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package signercontroller + +import ( + "context" + "errors" + "fmt" + "log/slog" + "time" + + "github.com/agent-substrate/substrate/internal/rendezvous" + certsv1beta1 "k8s.io/api/certificates/v1beta1" + apiequality "k8s.io/apimachinery/pkg/api/equality" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + certinformersv1beta1 "k8s.io/client-go/informers/certificates/v1beta1" + "k8s.io/client-go/kubernetes" + certlistersv1beta1 "k8s.io/client-go/listers/certificates/v1beta1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/utils/clock" +) + +type SignerImpl interface { + SignerName() string + DesiredClusterTrustBundles() []*certsv1beta1.ClusterTrustBundle + MakeCert(context.Context, *certsv1beta1.PodCertificateRequest) error +} + +type Hasher interface { + AssignedToThisReplica(ctx context.Context, item string) bool +} + +// Controller is an in-memory signing controller for PodCertificateRequests. +type Controller struct { + clock clock.PassiveClock + + kc kubernetes.Interface + pcrInformer cache.SharedIndexInformer + pcrQueue workqueue.TypedRateLimitingInterface[string] + + hasher Hasher + + handler SignerImpl +} + +// New creates a new Controller. +func New(clock clock.PassiveClock, handler SignerImpl, kc kubernetes.Interface, hasher Hasher) *Controller { + pcrInformer := certinformersv1beta1.NewFilteredPodCertificateRequestInformer(kc, metav1.NamespaceAll, 24*time.Hour, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, + func(opts *metav1.ListOptions) { + }, + ) + + sc := &Controller{ + clock: clock, + kc: kc, + pcrInformer: pcrInformer, + pcrQueue: workqueue.NewTypedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[string]()), + handler: handler, + hasher: hasher, + } + + sc.pcrInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(new any) { + key, err := cache.MetaNamespaceKeyFunc(new) + if err != nil { + return + } + sc.pcrQueue.Add(key) + }, + UpdateFunc: func(old, new any) { + key, err := cache.MetaNamespaceKeyFunc(new) + if err != nil { + return + } + sc.pcrQueue.Add(key) + }, + DeleteFunc: func(old any) { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(old) + if err != nil { + return + } + sc.pcrQueue.Add(key) + }, + }) + + return sc +} + +func (c *Controller) Run(ctx context.Context) { + defer c.pcrQueue.ShutDown() + go c.pcrInformer.Run(ctx.Done()) + if !cache.WaitForCacheSync(ctx.Done(), c.pcrInformer.HasSynced) { + return + } + + go wait.UntilWithContext(ctx, c.runWorker, time.Second) + go wait.JitterUntilWithContext(ctx, c.ensureBundles, 5*time.Second, 1.0, true) + <-ctx.Done() +} + +func (c *Controller) runWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + key, quit := c.pcrQueue.Get() + if quit { + return false + } + defer c.pcrQueue.Done(key) + + namespace, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + slog.ErrorContext(ctx, "Error splitting key into namespace and name", + slog.String("err", err.Error()), + slog.String("key", key), + ) + return true + } + + pcr, err := certlistersv1beta1.NewPodCertificateRequestLister(c.pcrInformer.GetIndexer()).PodCertificateRequests(namespace).Get(name) + if k8serrors.IsNotFound(err) { + c.pcrQueue.Forget(key) + return true + } else if err != nil { + slog.ErrorContext(ctx, "Error while retrieving PodCertificateRequest", + slog.String("err", err.Error()), + slog.String("key", key), + ) + return true + } + + err = c.handlePCR(ctx, pcr) + if errors.Is(err, rendezvous.ErrNotAssigned) { + c.pcrQueue.AddRateLimited(key) + return true + } + if err != nil { + slog.ErrorContext(ctx, "Error while handling PodCertificateRequest", + slog.String("err", err.Error()), + slog.String("key", key), + ) + c.pcrQueue.AddRateLimited(key) + return true + } + + c.pcrQueue.Forget(key) + return true +} + +func (c *Controller) handlePCR(ctx context.Context, pcr *certsv1beta1.PodCertificateRequest) error { + if pcr.Spec.SignerName != c.handler.SignerName() { + // Return nil, since we are not going to magically start supporting this + // signer name by retaining the cert in the workqueue. + return nil + } + + // PodCertificateRequests don't have an approval stage, and the node + // restriction / isolation check is handled by kube-apiserver. + + for _, cond := range pcr.Status.Conditions { + if cond.Type == certsv1beta1.PodCertificateRequestConditionTypeIssued { + return nil + } + if cond.Type == certsv1beta1.PodCertificateRequestConditionTypeDenied { + return nil + } + if cond.Type == certsv1beta1.PodCertificateRequestConditionTypeFailed { + return nil + } + } + + if !c.hasher.AssignedToThisReplica(ctx, pcr.ObjectMeta.Namespace+"/"+pcr.ObjectMeta.Name) { + return rendezvous.ErrNotAssigned + } + + slog.InfoContext(ctx, "Processing PCR", slog.String("key", pcr.ObjectMeta.Namespace+"/"+pcr.ObjectMeta.Name)) + + err := c.handler.MakeCert(ctx, pcr) + if err != nil { + return fmt.Errorf("while converting PodCertificateRequest to x509.Certificate chain: %w", err) + } + + return nil +} + +func (c *Controller) ensureBundles(ctx context.Context) { + // Only one replica should try to maintain the trust bundles. + if !c.hasher.AssignedToThisReplica(ctx, "maintain-trust-bundles") { + return + } + + wantCTBs := c.handler.DesiredClusterTrustBundles() + + for _, wantCTB := range wantCTBs { + ctb, err := c.kc.CertificatesV1beta1().ClusterTrustBundles().Get(ctx, wantCTB.ObjectMeta.Name, metav1.GetOptions{}) + if k8serrors.IsNotFound(err) { + _, err = c.kc.CertificatesV1beta1().ClusterTrustBundles().Create(ctx, wantCTB, metav1.CreateOptions{}) + if err != nil { + slog.ErrorContext(ctx, "Error while creating ClusterTrustBundle", + slog.String("err", err.Error()), + slog.String("key", wantCTB.ObjectMeta.Name), + ) + return + } + return + } else if err != nil { + slog.ErrorContext(ctx, "Error while getting ClusterTrustBundle", + slog.String("err", err.Error()), + slog.String("key", wantCTB.ObjectMeta.Name), + ) + return + } + + if apiequality.Semantic.DeepEqual(wantCTB.Labels, ctb.Labels) && apiequality.Semantic.DeepEqual(wantCTB.Spec, ctb.Spec) { + slog.InfoContext(ctx, "ClusterTrustBundle already in correct state", + slog.String("key", wantCTB.ObjectMeta.Name), + ) + } + + ctb = ctb.DeepCopy() + ctb.ObjectMeta.Labels = wantCTB.Labels + ctb.Spec.TrustBundle = wantCTB.Spec.TrustBundle + + _, err = c.kc.CertificatesV1beta1().ClusterTrustBundles().Update(ctx, ctb, metav1.UpdateOptions{}) + if err != nil { + slog.ErrorContext(ctx, "Error while updating ClusterTrustBundle", + slog.String("err", err.Error()), + slog.String("key", wantCTB.ObjectMeta.Name), + ) + } + } +} diff --git a/internal/utils/utils.go b/internal/utils/utils.go new file mode 100644 index 000000000..08e49df46 --- /dev/null +++ b/internal/utils/utils.go @@ -0,0 +1,42 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// ProtoToTextString converts a proto message to a textproto string. +func ProtoToTextString(msg proto.Message) (string, error) { + marshaler := prototext.MarshalOptions{ + Indent: " ", // Optional: for pretty printing + } + b, err := marshaler.Marshal(msg) + if err != nil { + return "", err + } + return string(b), nil +} + +// TextStringToProto converts a textproto string to a proto message. +func TextStringToProto(textString string, msg proto.Message) error { + unmarshaler := prototext.UnmarshalOptions{} + err := unmarshaler.Unmarshal([]byte(textString), msg) + if err != nil { + return err + } + return nil +} diff --git a/manifests/agent-secret/agent-secret.yaml.tmpl b/manifests/agent-secret/agent-secret.yaml.tmpl new file mode 100644 index 000000000..89a60273c --- /dev/null +++ b/manifests/agent-secret/agent-secret.yaml.tmpl @@ -0,0 +1,53 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: ate-demo-secret-agent-v2 +--- +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: agent-secret + namespace: ate-demo-secret-agent-v2 +spec: + replicas: 8 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor +--- +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: agent-secret + namespace: ate-demo-secret-agent-v2 +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: agent-secret + image: ko://github.com/agent-substrate/substrate/demos/agent-secret + command: ["/ko-app/agent-secret"] + ports: + - containerPort: 80 + workerPoolRef: + namespace: ate-demo-secret-agent-v2 + name: agent-secret + snapshotsConfig: + location: gs://${BUCKET_NAME}/ate-demo-secret-agent-v2/ diff --git a/manifests/ate-install/ate-api-server.yaml b/manifests/ate-install/ate-api-server.yaml new file mode 100644 index 000000000..5103e9e32 --- /dev/null +++ b/manifests/ate-install/ate-api-server.yaml @@ -0,0 +1,172 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Define Permissions (Read-Only for Pods) +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ate-api-server-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +- apiGroups: ["ate.dev"] + resources: ["actortemplates"] + verbs: ["get", "watch", "list"] +--- +# Create Service Account for Workload Identity +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ate-api-server + namespace: ate-system +--- +# 4. Bind Identity to Permissions +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ate-api-server-binding +subjects: +- kind: ServiceAccount + name: ate-api-server + namespace: ate-system +roleRef: + kind: ClusterRole + name: ate-api-server-role + apiGroup: rbac.authorization.k8s.io +--- +# 5. Deploy the API Server +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ate-api-server-deployment + namespace: ate-system +spec: + replicas: 1 + selector: + matchLabels: + app: ate-api-server + template: + metadata: + labels: + app: ate-api-server + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9090" + spec: + serviceAccountName: ate-api-server + containers: + - name: ate-api-server + image: ko://github.com/agent-substrate/substrate/cmd/servers/ateapi + args: + - "--grpc-listen-addr=0.0.0.0:443" + - "--grpc-server-cred-bundle=/run/servicedns.podcert.ate.dev/credential-bundle.pem" + - --redis-cluster-address=@env + - --redis-ca-certs=/etc/valkey-ca/ca.crt + - --redis-use-iam-auth=@env + - --redis-tls-server-name=@env + - --redis-client-cert=@env + - --client-jwt-issuer=@env + - --client-jwt-audience=api.ate-system.svc + - --session-id-jwt-pool=/run/session-id-jwt-pool/pool.json + - --session-id-ca-pool=/run/session-id-ca-pool/pool.json + - --workerpool-ca-certs=/run/workerpool-ca-certs/trust-bundle.pem + env: + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317 + # Inject env vars from a ConfigMap created by each developer. This lets + # each developer customize their own redis address, etc, without having + # to edit this manifest, which can remain constant across all + # developers. + envFrom: + - configMapRef: + name: ate-api-server-envvars + optional: true + volumeMounts: + - name: "servicedns" + mountPath: "/run/servicedns.podcert.ate.dev" + - name: "session-id-jwt-pool" + mountPath: "/run/session-id-jwt-pool" + # Note: See README.md for how to generate this secret. + - name: "valkey-ca-certs" + mountPath: "/etc/valkey-ca" + readOnly: true + - name: "session-id-ca-pool" + mountPath: "/run/session-id-ca-pool" + readOnly: true + - name: "workerpool-ca-certs" + mountPath: "/run/workerpool-ca-certs" + readOnly: true + ports: + - containerPort: 443 + - name: prometheus + containerPort: 9090 + volumes: + - name: "servicedns" + projected: + sources: + - podCertificate: + signerName: servicedns.podcert.ate.dev/identity + keyType: ECDSAP256 + credentialBundlePath: credential-bundle.pem + - name: "session-id-jwt-pool" + projected: + sources: + - secret: + name: "session-id-jwt-pool" + items: + - key: "pool" + path: "pool.json" + - name: "valkey-ca-certs" + projected: + sources: + - secret: + name: "valkey-ca-certs" + items: + - key: "ca.crt" + path: "ca.crt" + - name: "session-id-ca-pool" + projected: + sources: + - secret: + name: "session-id-ca-pool" + items: + - key: "pool" + path: "pool.json" + - name: "workerpool-ca-certs" + projected: + sources: + - clusterTrustBundle: + signerName: podidentity.podcert.ate.dev/identity + labelSelector: + matchLabels: + podcert.ate.dev/canarying: live + path: trust-bundle.pem +--- +# 6. Expose the Session Assigner +apiVersion: v1 +kind: Service +metadata: + name: api + namespace: ate-system +spec: + type: ClusterIP + selector: + app: ate-api-server + ports: + - name: grpc + protocol: TCP + port: 443 + targetPort: 443 diff --git a/manifests/ate-install/ate-controller.yaml b/manifests/ate-install/ate-controller.yaml new file mode 100644 index 000000000..f23a66f0e --- /dev/null +++ b/manifests/ate-install/ate-controller.yaml @@ -0,0 +1,89 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +kind: Namespace +apiVersion: v1 +metadata: + name: ate-system + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ate-controller + namespace: ate-system + labels: + apps: ate-controller + + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ate-controller +subjects: +- kind: ServiceAccount + name: ate-controller + namespace: ate-system +roleRef: + kind: ClusterRole + name: ate-controller + apiGroup: rbac.authorization.k8s.io + +--- + +kind: Service +apiVersion: v1 +metadata: + name: ate-controller + namespace: ate-system + labels: + app: ate-controller +spec: + selector: + app: ate-controller + ports: + - name: metrics + port: 8080 + targetPort: metrics + protocol: TCP + +--- + +kind: Deployment +apiVersion: apps/v1 +metadata: + name: ate-controller + namespace: ate-system +spec: + replicas: 1 + selector: + matchLabels: + app: ate-controller + template: + metadata: + labels: + app: ate-controller + spec: + serviceAccountName: ate-controller + containers: + - name: ate-controller + image: ko://github.com/agent-substrate/substrate/cmd/servers/atecontroller + ports: + - name: metrics + containerPort: 8080 + protocol: TCP + - name: healthz + containerPort: 8081 + protocol: TCP \ No newline at end of file diff --git a/manifests/ate-install/ate-system-namespace.yaml b/manifests/ate-install/ate-system-namespace.yaml new file mode 100644 index 000000000..2bf74235e --- /dev/null +++ b/manifests/ate-install/ate-system-namespace.yaml @@ -0,0 +1,18 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: ate-system \ No newline at end of file diff --git a/manifests/ate-install/atelet.yaml b/manifests/ate-install/atelet.yaml new file mode 100644 index 000000000..940b353fd --- /dev/null +++ b/manifests/ate-install/atelet.yaml @@ -0,0 +1,98 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# 1. Create Service Account +apiVersion: v1 +kind: ServiceAccount +metadata: + name: atelet + namespace: ate-system +--- +# 2. Define Permissions +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: atelet-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +# 3. Bind Identity to Permissions +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: atelet-binding +subjects: +- kind: ServiceAccount + name: atelet + namespace: ate-system +roleRef: + kind: ClusterRole + name: atelet-role + apiGroup: rbac.authorization.k8s.io +--- +# 4. Create DaemonSet +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: atelet + namespace: ate-system + labels: + app: atelet +spec: + selector: + matchLabels: + app: atelet + template: + metadata: + labels: + app: atelet + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9090" + spec: + serviceAccountName: atelet + containers: + - name: atelet + image: ko://github.com/agent-substrate/substrate/cmd/servers/atelet + args: + - --gcp-auth-for-image-pulls=true + securityContext: + privileged: true + env: + - name: MY_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: http://opentelemetry-collector.gke-managed-otel.svc.cluster.local:4317 + - name: ATE_STORAGE_BACKEND + value: "gcs" + ports: + - name: grpc + containerPort: 8085 + hostPort: 8085 + - name: prometheus + containerPort: 9090 + hostPort: 9090 + protocol: TCP + volumeMounts: + - name: run-ateom + mountPath: /run/ateom-gvisor + volumes: + - name: run-ateom + hostPath: + path: /run/ateom-gvisor + type: DirectoryOrCreate \ No newline at end of file diff --git a/manifests/ate-install/atenet-dns.yaml b/manifests/ate-install/atenet-dns.yaml new file mode 100644 index 000000000..6cb4ebc46 --- /dev/null +++ b/manifests/ate-install/atenet-dns.yaml @@ -0,0 +1,176 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: atenet-dns + namespace: ate-system + labels: + app: dns +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: atenet-dns + namespace: ate-system +rules: +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch", "create", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: atenet-dns + namespace: ate-system +subjects: +- kind: ServiceAccount + name: atenet-dns + namespace: ate-system +roleRef: + kind: Role + name: atenet-dns + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: atenet-dns + namespace: kube-system +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch", "create", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: atenet-dns + namespace: kube-system +subjects: +- kind: ServiceAccount + name: atenet-dns + namespace: ate-system +roleRef: + kind: Role + name: atenet-dns + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dns + namespace: ate-system + labels: + app: dns +spec: + replicas: 1 + selector: + matchLabels: + app: dns + template: + metadata: + labels: + app: dns + spec: + serviceAccountName: atenet-dns + shareProcessNamespace: true + initContainers: + - name: init-dns + image: busybox:1.36 + command: ["sh", "-c"] + # Initial core file is sufficient to start CoreDNS but does not contain + # any additional configuration. The controller will update the Corefile. + args: + - | + cat <<'EOF' > /etc/coredns/Corefile + .:53 { + errors + health :8080 + ready :8181 + reload + } + EOF + volumeMounts: + - name: dns-config-volume + mountPath: /etc/coredns + containers: + - name: coredns + image: coredns/coredns:1.11.1 + imagePullPolicy: IfNotPresent + args: [ "-conf", "/etc/coredns/Corefile" ] + volumeMounts: + - name: dns-config-volume + mountPath: /etc/coredns + ports: + - name: dns + containerPort: 53 + protocol: UDP + - name: dns-tcp + containerPort: 53 + protocol: TCP + livenessProbe: + httpGet: + path: /health + port: 8080 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 5 + readinessProbe: + httpGet: + path: /ready + port: 8181 + scheme: HTTP + initialDelaySeconds: 5 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + - name: dns-controller + image: ko://github.com/agent-substrate/substrate/cmd/servers/atenet + args: + - "dns" + - "--log-level=debug" + - "--interval=10s" + - "--corefile-path=/etc/coredns/Corefile" + volumeMounts: + - name: dns-config-volume + mountPath: /etc/coredns + volumes: + - name: dns-config-volume + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: dns + namespace: ate-system + labels: + app: dns +spec: + selector: + app: dns + type: ClusterIP + ports: + - name: dns + port: 53 + protocol: UDP + - name: dns-tcp + port: 53 + protocol: TCP \ No newline at end of file diff --git a/manifests/ate-install/atenet-router.yaml b/manifests/ate-install/atenet-router.yaml new file mode 100644 index 000000000..e309cad0a --- /dev/null +++ b/manifests/ate-install/atenet-router.yaml @@ -0,0 +1,191 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: atenet-router + namespace: ate-system + labels: + app: atenet-router +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: atenet-router +rules: +- apiGroups: + - "ate.dev" + resources: + - actortemplates + verbs: + - get + - watch + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: atenet-router +subjects: +- kind: ServiceAccount + name: atenet-router + namespace: ate-system +roleRef: + kind: ClusterRole + name: atenet-router + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: atenet-router-envoy-config + namespace: ate-system +data: + envoy.yaml: | + admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9901 + + node: + id: substrate-envoy-node + cluster: substrate-router-cluster + + dynamic_resources: + lds_config: + resource_api_version: V3 + ads: {} + cds_config: + resource_api_version: V3 + ads: {} + ads_config: + api_type: GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + + static_resources: + clusters: + - name: xds_cluster + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + load_assignment: + cluster_name: xds_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 18000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: atenet-router + namespace: ate-system + labels: + app: atenet-router +spec: + replicas: 1 + selector: + matchLabels: + app: atenet-router + template: + metadata: + labels: + app: atenet-router + spec: + serviceAccountName: atenet-router + containers: + - name: atenet-router + image: ko://github.com/agent-substrate/substrate/cmd/servers/atenet + args: + - "router" + - "--standalone" + - "--namespace=ate-system" + - "--port-http=8080" + - "--port-xds=18000" + - "--port-extproc=50051" + - "--extproc-address=127.0.0.1" + - "--ateapi-address=api.ate-system.svc:443" + - "--status-port=4040" + - "--port-https=8443" + - "--envoy-cert-path=/run/servicedns.podcert.ate.dev/credential-bundle.pem" + ports: + - name: xds + containerPort: 18000 + - name: extproc + containerPort: 50051 + - name: status + containerPort: 4040 + - name: envoy + image: envoyproxy/envoy:v1.30-latest + command: + - "/usr/local/bin/envoy" + - "-c" + - "/etc/envoy/envoy.yaml" + - "--component-log-level" + - "upstream:debug,router:debug,ext_proc:debug" + ports: + - name: http + containerPort: 8080 + - name: https + containerPort: 8443 + - name: admin + containerPort: 9901 + volumeMounts: + - name: envoy-config + mountPath: /etc/envoy + - name: "servicedns" + mountPath: "/run/servicedns.podcert.ate.dev" + volumes: + - name: envoy-config + configMap: + name: atenet-router-envoy-config + - name: "servicedns" + projected: + sources: + - podCertificate: + signerName: servicedns.podcert.ate.dev/identity + keyType: ECDSAP256 + credentialBundlePath: credential-bundle.pem +--- +apiVersion: v1 +kind: Service +metadata: + name: atenet-router + namespace: ate-system +spec: + type: ClusterIP + selector: + app: atenet-router + ports: + - name: http + port: 80 + targetPort: 8080 + protocol: TCP + - name: https + port: 443 + targetPort: 8443 + protocol: TCP diff --git a/manifests/ate-install/generated/ate.dev_actortemplates.yaml b/manifests/ate-install/generated/ate.dev_actortemplates.yaml new file mode 100644 index 000000000..c3fd0aed6 --- /dev/null +++ b/manifests/ate-install/generated/ate.dev_actortemplates.yaml @@ -0,0 +1,468 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: actortemplates.ate.dev +spec: + group: ate.dev + names: + kind: ActorTemplate + listKind: ActorTemplateList + plural: actortemplates + shortNames: + - actortemplate + singular: actortemplate + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec defines the desired state of ActorTemplate + properties: + containers: + description: Containers is the workload definition. + items: + description: A single application container that you want to run + within a WorkerPool. + properties: + command: + description: Entrypoint array. Not executed within a shell. + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: Environment variables to set in the worker replicas. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Image to use for the worker replicas. + type: string + name: + description: Name of the container. + type: string + ports: + description: List of ports to expose from the container. + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + required: + - name + type: object + type: array + pauseImage: + description: |- + PauseImage is the container to use as the root sandbox container. + + Typically, set it to [1] for on-gcp, and [2] for off-gcp + + - [1] gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da + - [2] registry.k8s.io/pause:3.10.2@sha256:f548e0e8e3dc1896ca956272154dde3314e8cc4fde0a57577ee9fa1c63f5baf4 + type: string + runsc: + description: Parameters for fetching the runsc binary to use. + properties: + amd64: + description: Configuration for the amd64 binary. + properties: + sha256Hash: + description: |- + The SHA256 hash of the binary to download. Used both to name the + downloaded file (for preventing conflicts), and to check the integrity of + the downloaded file. + type: string + url: + description: |- + A gs:// URL pointing to a runsc binary that can be downloaded (possibly + with atelet's credentials). + type: string + required: + - sha256Hash + - url + type: object + arm64: + description: Configuration for the arm64 binary. + properties: + sha256Hash: + description: |- + The SHA256 hash of the binary to download. Used both to name the + downloaded file (for preventing conflicts), and to check the integrity of + the downloaded file. + type: string + url: + description: |- + A gs:// URL pointing to a runsc binary that can be downloaded (possibly + with atelet's credentials). + type: string + required: + - sha256Hash + - url + type: object + authentication: + description: How should atelet authenticate to download the runsc + binary? + properties: + gcp: + description: Use GCP application-default credentials. + type: object + type: object + type: object + snapshotsConfig: + description: Snapshots configuration for the actor. + properties: + location: + description: Location to store snapshots in. + type: string + required: + - location + type: object + workerPoolRef: + description: Name of the worker pool to use for the actor. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + required: + - pauseImage + - runsc + - snapshotsConfig + - workerPoolRef + type: object + status: + description: status is the observed state of ActorTemplate + properties: + conditions: + description: conditions defines the status conditions array + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + goldenActorID: + type: string + goldenSnapshot: + type: string + phase: + description: Phase of the actor template. + type: string + takeGoldenSnapshotAt: + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/manifests/ate-install/generated/ate.dev_workerpools.yaml b/manifests/ate-install/generated/ate.dev_workerpools.yaml new file mode 100644 index 000000000..fed3270ea --- /dev/null +++ b/manifests/ate-install/generated/ate.dev_workerpools.yaml @@ -0,0 +1,79 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: workerpools.ate.dev +spec: + group: ate.dev + names: + kind: WorkerPool + listKind: WorkerPoolList + plural: workerpools + shortNames: + - workerpool + singular: workerpool + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: WorkerPool is the Schema for the workerpools API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec defines the desired state of WorkerPool + properties: + ateomImage: + description: AteomImage is the ateom container image to deploy as + workers. + type: string + replicas: + description: Replicas is the number of worker pods to run. + format: int32 + type: integer + required: + - ateomImage + - replicas + type: object + status: + description: status is the observed state of WorkerPool + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/manifests/ate-install/generated/role.yaml b/manifests/ate-install/generated/role.yaml new file mode 100644 index 000000000..fbbe7b305 --- /dev/null +++ b/manifests/ate-install/generated/role.yaml @@ -0,0 +1,82 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ate-controller +rules: +- apiGroups: + - "" + resources: + - configmaps + - secrets + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - pods + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - ate.dev + resources: + - actortemplates + - workerpools + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - ate.dev + resources: + - actortemplates/finalizers + - workerpools/finalizers + verbs: + - update +- apiGroups: + - ate.dev + resources: + - actortemplates/status + - workerpools/status + verbs: + - get + - patch + - update diff --git a/manifests/ate-install/kind/atelet/kustomization.yaml b/manifests/ate-install/kind/atelet/kustomization.yaml new file mode 100644 index 000000000..d93c0eb62 --- /dev/null +++ b/manifests/ate-install/kind/atelet/kustomization.yaml @@ -0,0 +1,49 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../../atelet.yaml + +patches: + - patch: |- + apiVersion: apps/v1 + kind: DaemonSet + metadata: + name: atelet + namespace: ate-system + spec: + template: + spec: + containers: + - name: atelet + args: + - --gcp-auth-for-image-pulls=false + - --localhost-registry-replacement=kind-registry:5000 + env: + - name: ATE_STORAGE_BACKEND + value: s3 + - name: AWS_REGION + value: us-east-1 + - name: AWS_ENDPOINT_URL + value: http://rustfs.ate-system.svc:9000 + - name: AWS_S3_USE_PATH_STYLE + value: "true" + # TODO: use a secret / identity management + - name: AWS_ACCESS_KEY_ID + value: rustfsadmin + - name: AWS_SECRET_ACCESS_KEY + value: rustfsadmin diff --git a/manifests/ate-install/kind/kustomization.yaml b/manifests/ate-install/kind/kustomization.yaml new file mode 100644 index 000000000..71b5fb944 --- /dev/null +++ b/manifests/ate-install/kind/kustomization.yaml @@ -0,0 +1,26 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../ate-api-server.yaml + - ../ate-controller.yaml + - ./atelet + - ../atenet-dns.yaml + - ../atenet-router.yaml + - ../valkey.yaml + - ../pod-certificate-controller.yaml + - rustfs.yaml diff --git a/manifests/ate-install/kind/rustfs.yaml b/manifests/ate-install/kind/rustfs.yaml new file mode 100644 index 000000000..3d39498f2 --- /dev/null +++ b/manifests/ate-install/kind/rustfs.yaml @@ -0,0 +1,91 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: rustfs-data + namespace: ate-system +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: rustfs + namespace: ate-system +spec: + selector: + app: rustfs + ports: + - name: api + port: 9000 + targetPort: 9000 + - name: console + port: 9001 + targetPort: 9001 + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rustfs + namespace: ate-system +spec: + replicas: 1 + selector: + matchLabels: + app: rustfs + template: + metadata: + labels: + app: rustfs + spec: + securityContext: + runAsUser: 10001 + runAsGroup: 10001 + fsGroup: 10001 + containers: + - name: rustfs + image: rustfs/rustfs:1.0.0-beta.3@sha256:378642b05b7dcb4849fb77ebe6aca4ced1c3f66e7e504247df95a5c9018d3358 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9000 + name: api + - containerPort: 9001 + name: console + env: + - name: RUSTFS_ADDRESS + value: ":9000" + - name: RUSTFS_CONSOLE_ADDRESS + value: ":9001" + - name: RUSTFS_CONSOLE_ENABLE + value: "true" + - name: RUSTFS_VOLUMES + value: "/data" + - name: RUSTFS_ACCESS_KEY + value: "rustfsadmin" + - name: RUSTFS_SECRET_KEY + value: "rustfsadmin" + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + persistentVolumeClaim: + claimName: rustfs-data diff --git a/manifests/ate-install/pod-certificate-controller.yaml b/manifests/ate-install/pod-certificate-controller.yaml new file mode 100644 index 000000000..4393b5f14 --- /dev/null +++ b/manifests/ate-install/pod-certificate-controller.yaml @@ -0,0 +1,196 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: podcertificate-controller-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: podcert-ate-dev-signer +rules: +# The service signer needs to be able to read services and pods. +- apiGroups: + - "" + resources: + - services + - pods + verbs: + - get + - list + - watch +- apiGroups: + - certificates.k8s.io + resources: + - podcertificaterequests + verbs: + - get + - list + - watch + - update +- apiGroups: + - certificates.k8s.io + resources: + - clustertrustbundles + verbs: + - create + - get + - list + - watch + - update + - delete +- apiGroups: + - certificates.k8s.io + resources: + - podcertificaterequests/status + verbs: + - update +- apiGroups: + - certificates.k8s.io + resources: + - signers + resourceNames: + - servicedns.podcert.ate.dev/* + - podidentity.podcert.ate.dev/* + verbs: + - sign + - attest +- apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: podcert-ate-dev-signer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: podcert-ate-dev-signer +subjects: +- kind: ServiceAccount + namespace: podcertificate-controller-system + name: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: podcertificate-controller-system + name: coordinator +rules: +- apiGroups: + - "coordination.k8s.io" + resources: + - "leases" + verbs: + - create + - get + - list + - watch + - update + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: podcertificate-controller-is-a-coordinator + namespace: podcertificate-controller-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: coordinator +subjects: +- kind: ServiceAccount + namespace: podcertificate-controller-system + name: default +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: podcertificate-controller + namespace: podcertificate-controller-system + labels: + app: podcertificate-controller +spec: + replicas: 1 + selector: + matchLabels: + app: podcertificate-controller + template: + metadata: + labels: + app: podcertificate-controller + spec: + containers: + - name: controller + image: ko://github.com/agent-substrate/substrate/cmd/servers/podcertcontroller + args: + - --in-cluster=true + - --sharding-pod-namespace=$(POD_NAMESPACE) + - --sharding-pod-name=$(POD_NAME) + - --sharding-pod-uid=$(POD_UID) + - --sharding-application-name=podcertificate-controller + - --service-dns-ca-pool=/run/ca-state/service-dns-pool.json + - --pod-identity-ca-pool=/run/ca-state/pod-identity-pool.json + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_UID + valueFrom: + fieldRef: + fieldPath: metadata.uid + volumeMounts: + - name: "ca-state" + mountPath: "/run/ca-state" + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + readOnlyRootFilesystem: true + volumes: + - name: "ca-state" + projected: + sources: + - secret: + name: "service-dns-ca-pool" + items: + - key: "pool" + path: "service-dns-pool.json" + - secret: + name: "pod-identity-ca-pool" + items: + - key: "pool" + path: "pod-identity-pool.json" + dnsPolicy: Default + nodeSelector: + kubernetes.io/os: linux + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccountName: default + terminationGracePeriodSeconds: 30 \ No newline at end of file diff --git a/manifests/ate-install/valkey.yaml b/manifests/ate-install/valkey.yaml new file mode 100644 index 000000000..f0b09429b --- /dev/null +++ b/manifests/ate-install/valkey.yaml @@ -0,0 +1,213 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: valkey-config + namespace: ate-system +data: + valkey.conf: | + # Enforce TLS and disable standard port + port 0 + tls-port 6379 + tls-cluster yes + tls-replication yes + + # Load certificates from projected volume + tls-cert-file /run/servicedns.podcert.ate.dev/credential-bundle.pem + tls-key-file /run/servicedns.podcert.ate.dev/credential-bundle.pem + tls-ca-cert-file /etc/valkey-ca/ca.crt + tls-auth-clients yes + + # Enable cluster mode + cluster-enabled yes + cluster-config-file nodes.conf + cluster-node-timeout 5000 + appendonly yes + protected-mode no +--- +apiVersion: v1 +kind: Service +metadata: + name: valkey-cluster-service + namespace: ate-system +spec: + clusterIP: None + selector: + app: valkey-cluster + ports: + - name: valkey + port: 6379 + targetPort: 6379 + - name: bus + port: 16379 + targetPort: 16379 +--- +apiVersion: v1 +kind: Service +metadata: + name: valkey-cluster + namespace: ate-system +spec: + selector: + app: valkey-cluster + ports: + - name: valkey + port: 6379 + targetPort: 6379 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: valkey-cluster + namespace: ate-system +spec: + serviceName: valkey-cluster-service + replicas: 6 + podManagementPolicy: Parallel + selector: + matchLabels: + app: valkey-cluster + template: + metadata: + labels: + app: valkey-cluster + spec: + containers: + - name: valkey + image: valkey/valkey:8.0 + command: ["valkey-server", "/etc/valkey/valkey.conf"] + ports: + - name: valkey + containerPort: 6379 + - name: bus + containerPort: 16379 + volumeMounts: + - name: config + mountPath: /etc/valkey + - name: servicedns + mountPath: /run/servicedns.podcert.ate.dev + - name: valkey-ca-certs + mountPath: /etc/valkey-ca + readOnly: true + - name: data + mountPath: /data + volumes: + - name: config + configMap: + name: valkey-config + - name: servicedns + projected: + sources: + - podCertificate: + signerName: servicedns.podcert.ate.dev/identity + keyType: ECDSAP256 + credentialBundlePath: credential-bundle.pem + - name: valkey-ca-certs + projected: + sources: + - secret: + name: valkey-ca-certs + items: + - key: ca.crt + path: ca.crt + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: valkey-cluster-init + namespace: ate-system +spec: + template: + metadata: + labels: + app: valkey-cluster-init + spec: + restartPolicy: OnFailure + containers: + - name: init + image: valkey/valkey:8.0 + volumeMounts: + - name: servicedns + mountPath: /run/servicedns.podcert.ate.dev + - name: valkey-ca-certs + mountPath: /etc/valkey-ca + readOnly: true + command: + - /bin/sh + - -c + - | + set -e + echo "Waiting for all Valkey pods to resolve..." + for i in 0 1 2 3 4 5; do + until getent hosts valkey-cluster-${i}.valkey-cluster-service.ate-system.svc >/dev/null 2>&1; do + echo "Waiting for valkey-cluster-${i} DNS..." + sleep 2 + done + done + + echo "All pods resolved. Getting IPs..." + POD_IPS="" + for i in 0 1 2 3 4 5; do + ip=$(getent hosts valkey-cluster-${i}.valkey-cluster-service.ate-system.svc | awk '{print $1}') + POD_IPS="${POD_IPS} ${ip}:6379" + done + + echo "Checking if Valkey cluster is already initialized..." + until valkey-cli --tls --cacert /etc/valkey-ca/ca.crt --cert /run/servicedns.podcert.ate.dev/credential-bundle.pem --key /run/servicedns.podcert.ate.dev/credential-bundle.pem -h valkey-cluster-0.valkey-cluster-service.ate-system.svc ping >/dev/null 2>&1; do + echo "Waiting for valkey-cluster-0 to respond to ping..." + sleep 2 + done + + INIT_STATUS=$(valkey-cli --tls --cacert /etc/valkey-ca/ca.crt --cert /run/servicedns.podcert.ate.dev/credential-bundle.pem --key /run/servicedns.podcert.ate.dev/credential-bundle.pem -h valkey-cluster-0.valkey-cluster-service.ate-system.svc cluster info 2>/dev/null | grep cluster_state || true) + + if [ -z "${INIT_STATUS}" ] || ! echo "${INIT_STATUS}" | grep -q "cluster_state:ok"; then + echo "Initializing Valkey cluster..." + valkey-cli --tls \ + --cacert /etc/valkey-ca/ca.crt \ + --cert /run/servicedns.podcert.ate.dev/credential-bundle.pem \ + --key /run/servicedns.podcert.ate.dev/credential-bundle.pem \ + --cluster create ${POD_IPS} \ + --cluster-replicas 1 \ + --cluster-yes + echo "Cluster initialization complete!" + else + echo "Cluster already initialized." + fi + volumes: + - name: servicedns + projected: + sources: + - podCertificate: + signerName: servicedns.podcert.ate.dev/identity + keyType: ECDSAP256 + credentialBundlePath: credential-bundle.pem + - name: valkey-ca-certs + projected: + sources: + - secret: + name: valkey-ca-certs + items: + - key: ca.crt + path: ca.crt + diff --git a/manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl b/manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl new file mode 100644 index 000000000..1c2637bea --- /dev/null +++ b/manifests/claude-code-multiplex/claude-code-multiplex.yaml.tmpl @@ -0,0 +1,148 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Three ActorTemplates share a 2-pod WorkerPool, so substrate must suspend +# at least one actor at any moment. ANTHROPIC_API_KEY is passed as a plain +# env var per dberkov's PR #203 review — substrate does not currently +# support `valueFrom.secretKeyRef` on ActorTemplate container env. +# +# WORKLOAD_IMAGE is the resolved sha256-digest reference for the +# claude-multiplex-demo-workload image — built and pushed to +# ${KO_DOCKER_REPO} by `./hack/install-ate.sh --deploy-demo-claude-code-multiplex`, +# substituted into this template at apply time. + +apiVersion: v1 +kind: Namespace +metadata: + name: claude-multiplex-demo + +--- + +# 2 worker replicas for 3 actors — the multiplex pressure that makes the +# substrate suspend/resume behavior visible. +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: claude-workerpool + namespace: claude-multiplex-demo +spec: + replicas: 2 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor + +--- + +# Three ActorTemplates, each running the same workload image with a +# distinct TASK prompt. Each template spawns one named actor, so there +# are 3 actors competing for 2 worker pods → substrate must suspend +# at least one at any moment. + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: agent-luna + namespace: claude-multiplex-demo +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: claude + image: ${WORKLOAD_IMAGE} + env: + - name: ACTOR_NAME + value: "luna" + - name: TASK + value: "Tell me one short, surprising fact about the Moon. One sentence." + - name: INTERVAL_SECONDS + value: "45" + - name: ANTHROPIC_API_KEY + value: "${ANTHROPIC_API_KEY}" + workerPoolRef: + namespace: claude-multiplex-demo + name: claude-workerpool + snapshotsConfig: + location: gs://${BUCKET_NAME}/claude-multiplex-demo/ + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: agent-mars + namespace: claude-multiplex-demo +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: claude + image: ${WORKLOAD_IMAGE} + env: + - name: ACTOR_NAME + value: "mars" + - name: TASK + value: "Give me one concise tip for learning a new programming language. One sentence." + - name: INTERVAL_SECONDS + value: "45" + - name: ANTHROPIC_API_KEY + value: "${ANTHROPIC_API_KEY}" + workerPoolRef: + namespace: claude-multiplex-demo + name: claude-workerpool + snapshotsConfig: + location: gs://${BUCKET_NAME}/claude-multiplex-demo/ + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: agent-orion + namespace: claude-multiplex-demo +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: claude + image: ${WORKLOAD_IMAGE} + env: + - name: ACTOR_NAME + value: "orion" + - name: TASK + value: "Suggest one healthy meal that takes under 15 minutes to prepare. One sentence." + - name: INTERVAL_SECONDS + value: "45" + - name: ANTHROPIC_API_KEY + value: "${ANTHROPIC_API_KEY}" + workerPoolRef: + namespace: claude-multiplex-demo + name: claude-workerpool + snapshotsConfig: + location: gs://${BUCKET_NAME}/claude-multiplex-demo/ diff --git a/manifests/counter/counter.yaml.tmpl b/manifests/counter/counter.yaml.tmpl new file mode 100644 index 000000000..320ea753b --- /dev/null +++ b/manifests/counter/counter.yaml.tmpl @@ -0,0 +1,55 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: ate-demo-counter + +--- + +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: counter + namespace: ate-demo-counter +spec: + replicas: 5 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor + +--- + +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: counter + namespace: ate-demo-counter +spec: + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: counter + image: ko://github.com/agent-substrate/substrate/demos/counter + command: ["/ko-app/counter"] + workerPoolRef: + namespace: ate-demo-counter + name: counter + snapshotsConfig: + location: gs://${BUCKET_NAME}/ate-demo-counter/ diff --git a/manifests/sandbox/sandbox.yaml.tmpl b/manifests/sandbox/sandbox.yaml.tmpl new file mode 100644 index 000000000..2277e9167 --- /dev/null +++ b/manifests/sandbox/sandbox.yaml.tmpl @@ -0,0 +1,56 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Namespace +metadata: + name: ate-demo-sandbox +--- +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: sandbox-workerpool + namespace: ate-demo-sandbox +spec: + replicas: 2 + ateomImage: ko://github.com/agent-substrate/substrate/cmd/servers/ateom-gvisor +--- +apiVersion: ate.dev/v1alpha1 +kind: ActorTemplate +metadata: + name: sandbox-template + namespace: ate-demo-sandbox +spec: + workerPoolRef: + name: sandbox-workerpool + namespace: ate-demo-sandbox + runsc: + amd64: + url: "gs://gvisor/releases/nightly/2026-05-19/x86_64/runsc" + sha256Hash: "a397be1abc2420d26bce6c70e6e2ff96c73aaaab929756c56f5e2089ea842b63" + arm64: + url: "gs://gvisor/releases/nightly/2026-05-19/aarch64/runsc" + sha256Hash: "1ba2366ae2efceba166046f51a4104f9261c9cb72c6db8f5b3fe2dc57dea86b9" + pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" + containers: + - name: sandbox + image: ko://github.com/agent-substrate/substrate/demos/sandbox + command: ["/ko-app/sandbox"] + ports: + - containerPort: 80 + env: + - name: PORT + value: "80" + snapshotsConfig: + location: gs://${BUCKET_NAME}/ate-demo-counter/ diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go new file mode 100644 index 000000000..25935b0d1 --- /dev/null +++ b/pkg/client/clientset/versioned/clientset.go @@ -0,0 +1,118 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + fmt "fmt" + http "net/http" + + apiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/typed/api/v1alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + ApiV1alpha1() apiv1alpha1.ApiV1alpha1Interface +} + +// Clientset contains the clients for groups. +type Clientset struct { + *discovery.DiscoveryClient + apiV1alpha1 *apiv1alpha1.ApiV1alpha1Client +} + +// ApiV1alpha1 retrieves the ApiV1alpha1Client +func (c *Clientset) ApiV1alpha1() apiv1alpha1.ApiV1alpha1Interface { + return c.apiV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + + // share the transport between all clients + httpClient, err := rest.HTTPClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return NewForConfigAndClient(&configShallowCopy, httpClient) +} + +// NewForConfigAndClient creates a new Clientset for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. +func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + + var cs Clientset + var err error + cs.apiV1alpha1, err = apiv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + cs, err := NewForConfig(c) + if err != nil { + panic(err) + } + return cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.apiV1alpha1 = apiv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 000000000..799b57156 --- /dev/null +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,103 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + clientset "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + apiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/typed/api/v1alpha1" + fakeapiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/typed/api/v1alpha1/fake" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +// +// Deprecated: NewClientset replaces this with support for field management, which significantly improves +// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. +// via --with-applyconfig). +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + var opts metav1.ListOptions + if watchAction, ok := action.(testing.WatchActionImpl); ok { + opts = watchAction.ListOptions + } + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns, opts) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +// IsWatchListSemanticsSupported informs the reflector that this client +// doesn't support WatchList semantics. +// +// This is a synthetic method whose sole purpose is to satisfy the optional +// interface check performed by the reflector. +// Returning true signals that WatchList can NOT be used. +// No additional logic is implemented here. +func (c *Clientset) IsWatchListSemanticsUnSupported() bool { + return true +} + +var ( + _ clientset.Interface = &Clientset{} + _ testing.FakeClient = &Clientset{} +) + +// ApiV1alpha1 retrieves the ApiV1alpha1Client +func (c *Clientset) ApiV1alpha1() apiv1alpha1.ApiV1alpha1Interface { + return &fakeapiv1alpha1.FakeApiV1alpha1{Fake: &c.Fake} +} diff --git a/pkg/client/clientset/versioned/fake/doc.go b/pkg/client/clientset/versioned/fake/doc.go new file mode 100644 index 000000000..8595156a0 --- /dev/null +++ b/pkg/client/clientset/versioned/fake/doc.go @@ -0,0 +1,18 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go new file mode 100644 index 000000000..0ddd9f36d --- /dev/null +++ b/pkg/client/clientset/versioned/fake/register.go @@ -0,0 +1,54 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + apiv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/pkg/client/clientset/versioned/scheme/doc.go b/pkg/client/clientset/versioned/scheme/doc.go new file mode 100644 index 000000000..25b03b440 --- /dev/null +++ b/pkg/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,18 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go new file mode 100644 index 000000000..b8ebfea02 --- /dev/null +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -0,0 +1,54 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + apiv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/actortemplate.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/actortemplate.go new file mode 100644 index 000000000..3f589e06a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/actortemplate.go @@ -0,0 +1,68 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + scheme "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// ActorTemplatesGetter has a method to return a ActorTemplateInterface. +// A group's client should implement this interface. +type ActorTemplatesGetter interface { + ActorTemplates(namespace string) ActorTemplateInterface +} + +// ActorTemplateInterface has methods to work with ActorTemplate resources. +type ActorTemplateInterface interface { + Create(ctx context.Context, actorTemplate *apiv1alpha1.ActorTemplate, opts v1.CreateOptions) (*apiv1alpha1.ActorTemplate, error) + Update(ctx context.Context, actorTemplate *apiv1alpha1.ActorTemplate, opts v1.UpdateOptions) (*apiv1alpha1.ActorTemplate, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, actorTemplate *apiv1alpha1.ActorTemplate, opts v1.UpdateOptions) (*apiv1alpha1.ActorTemplate, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*apiv1alpha1.ActorTemplate, error) + List(ctx context.Context, opts v1.ListOptions) (*apiv1alpha1.ActorTemplateList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *apiv1alpha1.ActorTemplate, err error) + ActorTemplateExpansion +} + +// actorTemplates implements ActorTemplateInterface +type actorTemplates struct { + *gentype.ClientWithList[*apiv1alpha1.ActorTemplate, *apiv1alpha1.ActorTemplateList] +} + +// newActorTemplates returns a ActorTemplates +func newActorTemplates(c *ApiV1alpha1Client, namespace string) *actorTemplates { + return &actorTemplates{ + gentype.NewClientWithList[*apiv1alpha1.ActorTemplate, *apiv1alpha1.ActorTemplateList]( + "actortemplates", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *apiv1alpha1.ActorTemplate { return &apiv1alpha1.ActorTemplate{} }, + func() *apiv1alpha1.ActorTemplateList { return &apiv1alpha1.ActorTemplateList{} }, + ), + } +} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/api_client.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/api_client.go new file mode 100644 index 000000000..7fec0a38a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/api_client.go @@ -0,0 +1,104 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + http "net/http" + + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + scheme "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type ApiV1alpha1Interface interface { + RESTClient() rest.Interface + ActorTemplatesGetter + WorkerPoolsGetter +} + +// ApiV1alpha1Client is used to interact with features provided by the api group. +type ApiV1alpha1Client struct { + restClient rest.Interface +} + +func (c *ApiV1alpha1Client) ActorTemplates(namespace string) ActorTemplateInterface { + return newActorTemplates(c, namespace) +} + +func (c *ApiV1alpha1Client) WorkerPools(namespace string) WorkerPoolInterface { + return newWorkerPools(c, namespace) +} + +// NewForConfig creates a new ApiV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*ApiV1alpha1Client, error) { + config := *c + setConfigDefaults(&config) + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new ApiV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ApiV1alpha1Client, error) { + config := *c + setConfigDefaults(&config) + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &ApiV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new ApiV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ApiV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new ApiV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *ApiV1alpha1Client { + return &ApiV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) { + gv := apiv1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *ApiV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/doc.go new file mode 100644 index 000000000..c01ce2465 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/doc.go @@ -0,0 +1,18 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/doc.go new file mode 100644 index 000000000..f9c3d48a0 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/doc.go @@ -0,0 +1,18 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_actortemplate.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_actortemplate.go new file mode 100644 index 000000000..ed7eebd2c --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_actortemplate.go @@ -0,0 +1,50 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + apiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/typed/api/v1alpha1" + gentype "k8s.io/client-go/gentype" +) + +// fakeActorTemplates implements ActorTemplateInterface +type fakeActorTemplates struct { + *gentype.FakeClientWithList[*v1alpha1.ActorTemplate, *v1alpha1.ActorTemplateList] + Fake *FakeApiV1alpha1 +} + +func newFakeActorTemplates(fake *FakeApiV1alpha1, namespace string) apiv1alpha1.ActorTemplateInterface { + return &fakeActorTemplates{ + gentype.NewFakeClientWithList[*v1alpha1.ActorTemplate, *v1alpha1.ActorTemplateList]( + fake.Fake, + namespace, + v1alpha1.SchemeGroupVersion.WithResource("actortemplates"), + v1alpha1.SchemeGroupVersion.WithKind("ActorTemplate"), + func() *v1alpha1.ActorTemplate { return &v1alpha1.ActorTemplate{} }, + func() *v1alpha1.ActorTemplateList { return &v1alpha1.ActorTemplateList{} }, + func(dst, src *v1alpha1.ActorTemplateList) { dst.ListMeta = src.ListMeta }, + func(list *v1alpha1.ActorTemplateList) []*v1alpha1.ActorTemplate { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v1alpha1.ActorTemplateList, items []*v1alpha1.ActorTemplate) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_api_client.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_api_client.go new file mode 100644 index 000000000..bcb612ae4 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_api_client.go @@ -0,0 +1,42 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/typed/api/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeApiV1alpha1 struct { + *testing.Fake +} + +func (c *FakeApiV1alpha1) ActorTemplates(namespace string) v1alpha1.ActorTemplateInterface { + return newFakeActorTemplates(c, namespace) +} + +func (c *FakeApiV1alpha1) WorkerPools(namespace string) v1alpha1.WorkerPoolInterface { + return newFakeWorkerPools(c, namespace) +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeApiV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_workerpool.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_workerpool.go new file mode 100644 index 000000000..d9ad840e1 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/fake/fake_workerpool.go @@ -0,0 +1,48 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + apiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/typed/api/v1alpha1" + gentype "k8s.io/client-go/gentype" +) + +// fakeWorkerPools implements WorkerPoolInterface +type fakeWorkerPools struct { + *gentype.FakeClientWithList[*v1alpha1.WorkerPool, *v1alpha1.WorkerPoolList] + Fake *FakeApiV1alpha1 +} + +func newFakeWorkerPools(fake *FakeApiV1alpha1, namespace string) apiv1alpha1.WorkerPoolInterface { + return &fakeWorkerPools{ + gentype.NewFakeClientWithList[*v1alpha1.WorkerPool, *v1alpha1.WorkerPoolList]( + fake.Fake, + namespace, + v1alpha1.SchemeGroupVersion.WithResource("workerpools"), + v1alpha1.SchemeGroupVersion.WithKind("WorkerPool"), + func() *v1alpha1.WorkerPool { return &v1alpha1.WorkerPool{} }, + func() *v1alpha1.WorkerPoolList { return &v1alpha1.WorkerPoolList{} }, + func(dst, src *v1alpha1.WorkerPoolList) { dst.ListMeta = src.ListMeta }, + func(list *v1alpha1.WorkerPoolList) []*v1alpha1.WorkerPool { return gentype.ToPointerSlice(list.Items) }, + func(list *v1alpha1.WorkerPoolList, items []*v1alpha1.WorkerPool) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..6df992515 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type ActorTemplateExpansion interface{} + +type WorkerPoolExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/api/v1alpha1/workerpool.go b/pkg/client/clientset/versioned/typed/api/v1alpha1/workerpool.go new file mode 100644 index 000000000..1c62c805f --- /dev/null +++ b/pkg/client/clientset/versioned/typed/api/v1alpha1/workerpool.go @@ -0,0 +1,68 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + scheme "github.com/agent-substrate/substrate/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// WorkerPoolsGetter has a method to return a WorkerPoolInterface. +// A group's client should implement this interface. +type WorkerPoolsGetter interface { + WorkerPools(namespace string) WorkerPoolInterface +} + +// WorkerPoolInterface has methods to work with WorkerPool resources. +type WorkerPoolInterface interface { + Create(ctx context.Context, workerPool *apiv1alpha1.WorkerPool, opts v1.CreateOptions) (*apiv1alpha1.WorkerPool, error) + Update(ctx context.Context, workerPool *apiv1alpha1.WorkerPool, opts v1.UpdateOptions) (*apiv1alpha1.WorkerPool, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, workerPool *apiv1alpha1.WorkerPool, opts v1.UpdateOptions) (*apiv1alpha1.WorkerPool, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*apiv1alpha1.WorkerPool, error) + List(ctx context.Context, opts v1.ListOptions) (*apiv1alpha1.WorkerPoolList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *apiv1alpha1.WorkerPool, err error) + WorkerPoolExpansion +} + +// workerPools implements WorkerPoolInterface +type workerPools struct { + *gentype.ClientWithList[*apiv1alpha1.WorkerPool, *apiv1alpha1.WorkerPoolList] +} + +// newWorkerPools returns a WorkerPools +func newWorkerPools(c *ApiV1alpha1Client, namespace string) *workerPools { + return &workerPools{ + gentype.NewClientWithList[*apiv1alpha1.WorkerPool, *apiv1alpha1.WorkerPoolList]( + "workerpools", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *apiv1alpha1.WorkerPool { return &apiv1alpha1.WorkerPool{} }, + func() *apiv1alpha1.WorkerPoolList { return &apiv1alpha1.WorkerPoolList{} }, + ), + } +} diff --git a/pkg/client/informers/externalversions/api/interface.go b/pkg/client/informers/externalversions/api/interface.go new file mode 100644 index 000000000..eaaa7d06a --- /dev/null +++ b/pkg/client/informers/externalversions/api/interface.go @@ -0,0 +1,44 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package api + +import ( + v1alpha1 "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/api/v1alpha1" + internalinterfaces "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/api/v1alpha1/actortemplate.go b/pkg/client/informers/externalversions/api/v1alpha1/actortemplate.go new file mode 100644 index 000000000..ea74a0487 --- /dev/null +++ b/pkg/client/informers/externalversions/api/v1alpha1/actortemplate.go @@ -0,0 +1,100 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + time "time" + + substrateapiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + versioned "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + internalinterfaces "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/internalinterfaces" + apiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ActorTemplateInformer provides access to a shared informer and lister for +// ActorTemplates. +type ActorTemplateInformer interface { + Informer() cache.SharedIndexInformer + Lister() apiv1alpha1.ActorTemplateLister +} + +type actorTemplateInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewActorTemplateInformer constructs a new informer for ActorTemplate type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewActorTemplateInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredActorTemplateInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredActorTemplateInformer constructs a new informer for ActorTemplate type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredActorTemplateInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().ActorTemplates(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().ActorTemplates(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().ActorTemplates(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().ActorTemplates(namespace).Watch(ctx, options) + }, + }, client), + &substrateapiv1alpha1.ActorTemplate{}, + resyncPeriod, + indexers, + ) +} + +func (f *actorTemplateInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredActorTemplateInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *actorTemplateInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&substrateapiv1alpha1.ActorTemplate{}, f.defaultInformer) +} + +func (f *actorTemplateInformer) Lister() apiv1alpha1.ActorTemplateLister { + return apiv1alpha1.NewActorTemplateLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/api/v1alpha1/interface.go b/pkg/client/informers/externalversions/api/v1alpha1/interface.go new file mode 100644 index 000000000..dc453e84f --- /dev/null +++ b/pkg/client/informers/externalversions/api/v1alpha1/interface.go @@ -0,0 +1,50 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ActorTemplates returns a ActorTemplateInformer. + ActorTemplates() ActorTemplateInformer + // WorkerPools returns a WorkerPoolInformer. + WorkerPools() WorkerPoolInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ActorTemplates returns a ActorTemplateInformer. +func (v *version) ActorTemplates() ActorTemplateInformer { + return &actorTemplateInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// WorkerPools returns a WorkerPoolInformer. +func (v *version) WorkerPools() WorkerPoolInformer { + return &workerPoolInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/api/v1alpha1/workerpool.go b/pkg/client/informers/externalversions/api/v1alpha1/workerpool.go new file mode 100644 index 000000000..60ea7b146 --- /dev/null +++ b/pkg/client/informers/externalversions/api/v1alpha1/workerpool.go @@ -0,0 +1,100 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + context "context" + time "time" + + substrateapiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + versioned "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + internalinterfaces "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/internalinterfaces" + apiv1alpha1 "github.com/agent-substrate/substrate/pkg/client/listers/api/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// WorkerPoolInformer provides access to a shared informer and lister for +// WorkerPools. +type WorkerPoolInformer interface { + Informer() cache.SharedIndexInformer + Lister() apiv1alpha1.WorkerPoolLister +} + +type workerPoolInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewWorkerPoolInformer constructs a new informer for WorkerPool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewWorkerPoolInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredWorkerPoolInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredWorkerPoolInformer constructs a new informer for WorkerPool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredWorkerPoolInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().WorkerPools(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().WorkerPools(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().WorkerPools(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ApiV1alpha1().WorkerPools(namespace).Watch(ctx, options) + }, + }, client), + &substrateapiv1alpha1.WorkerPool{}, + resyncPeriod, + indexers, + ) +} + +func (f *workerPoolInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredWorkerPoolInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *workerPoolInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&substrateapiv1alpha1.WorkerPool{}, f.defaultInformer) +} + +func (f *workerPoolInformer) Lister() apiv1alpha1.WorkerPoolLister { + return apiv1alpha1.NewWorkerPoolLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go new file mode 100644 index 000000000..f4fdc6cdb --- /dev/null +++ b/pkg/client/informers/externalversions/factory.go @@ -0,0 +1,261 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + api "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/api" + internalinterfaces "github.com/agent-substrate/substrate/pkg/client/informers/externalversions/internalinterfaces" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + transform cache.TransformFunc + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// WithTransform sets a transform on all informers. +func WithTransform(transform cache.TransformFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.transform = transform + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + if f.shuttingDown { + return + } + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() + f.startedInformers[informerType] = true + } + } +} + +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + informer.SetTransform(f.transform) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.WithCancel(context.Background()) +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + + Api() api.Interface +} + +func (f *sharedInformerFactory) Api() api.Interface { + return api.New(f, f.namespace, f.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go new file mode 100644 index 000000000..0c9f643af --- /dev/null +++ b/pkg/client/informers/externalversions/generic.go @@ -0,0 +1,62 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + fmt "fmt" + + v1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=api, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("actortemplates"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Api().V1alpha1().ActorTemplates().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("workerpools"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Api().V1alpha1().WorkerPools().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 000000000..78f1f1ceb --- /dev/null +++ b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,38 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + versioned "github.com/agent-substrate/substrate/pkg/client/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/pkg/client/listers/api/v1alpha1/actortemplate.go b/pkg/client/listers/api/v1alpha1/actortemplate.go new file mode 100644 index 000000000..c40869b51 --- /dev/null +++ b/pkg/client/listers/api/v1alpha1/actortemplate.go @@ -0,0 +1,68 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// ActorTemplateLister helps list ActorTemplates. +// All objects returned here must be treated as read-only. +type ActorTemplateLister interface { + // List lists all ActorTemplates in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apiv1alpha1.ActorTemplate, err error) + // ActorTemplates returns an object that can list and get ActorTemplates. + ActorTemplates(namespace string) ActorTemplateNamespaceLister + ActorTemplateListerExpansion +} + +// actorTemplateLister implements the ActorTemplateLister interface. +type actorTemplateLister struct { + listers.ResourceIndexer[*apiv1alpha1.ActorTemplate] +} + +// NewActorTemplateLister returns a new ActorTemplateLister. +func NewActorTemplateLister(indexer cache.Indexer) ActorTemplateLister { + return &actorTemplateLister{listers.New[*apiv1alpha1.ActorTemplate](indexer, apiv1alpha1.Resource("actortemplate"))} +} + +// ActorTemplates returns an object that can list and get ActorTemplates. +func (s *actorTemplateLister) ActorTemplates(namespace string) ActorTemplateNamespaceLister { + return actorTemplateNamespaceLister{listers.NewNamespaced[*apiv1alpha1.ActorTemplate](s.ResourceIndexer, namespace)} +} + +// ActorTemplateNamespaceLister helps list and get ActorTemplates. +// All objects returned here must be treated as read-only. +type ActorTemplateNamespaceLister interface { + // List lists all ActorTemplates in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apiv1alpha1.ActorTemplate, err error) + // Get retrieves the ActorTemplate from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*apiv1alpha1.ActorTemplate, error) + ActorTemplateNamespaceListerExpansion +} + +// actorTemplateNamespaceLister implements the ActorTemplateNamespaceLister +// interface. +type actorTemplateNamespaceLister struct { + listers.ResourceIndexer[*apiv1alpha1.ActorTemplate] +} diff --git a/pkg/client/listers/api/v1alpha1/expansion_generated.go b/pkg/client/listers/api/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..c524acf68 --- /dev/null +++ b/pkg/client/listers/api/v1alpha1/expansion_generated.go @@ -0,0 +1,33 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// ActorTemplateListerExpansion allows custom methods to be added to +// ActorTemplateLister. +type ActorTemplateListerExpansion interface{} + +// ActorTemplateNamespaceListerExpansion allows custom methods to be added to +// ActorTemplateNamespaceLister. +type ActorTemplateNamespaceListerExpansion interface{} + +// WorkerPoolListerExpansion allows custom methods to be added to +// WorkerPoolLister. +type WorkerPoolListerExpansion interface{} + +// WorkerPoolNamespaceListerExpansion allows custom methods to be added to +// WorkerPoolNamespaceLister. +type WorkerPoolNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/api/v1alpha1/workerpool.go b/pkg/client/listers/api/v1alpha1/workerpool.go new file mode 100644 index 000000000..5be839ac4 --- /dev/null +++ b/pkg/client/listers/api/v1alpha1/workerpool.go @@ -0,0 +1,68 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + apiv1alpha1 "github.com/agent-substrate/substrate/api/v1alpha1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// WorkerPoolLister helps list WorkerPools. +// All objects returned here must be treated as read-only. +type WorkerPoolLister interface { + // List lists all WorkerPools in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apiv1alpha1.WorkerPool, err error) + // WorkerPools returns an object that can list and get WorkerPools. + WorkerPools(namespace string) WorkerPoolNamespaceLister + WorkerPoolListerExpansion +} + +// workerPoolLister implements the WorkerPoolLister interface. +type workerPoolLister struct { + listers.ResourceIndexer[*apiv1alpha1.WorkerPool] +} + +// NewWorkerPoolLister returns a new WorkerPoolLister. +func NewWorkerPoolLister(indexer cache.Indexer) WorkerPoolLister { + return &workerPoolLister{listers.New[*apiv1alpha1.WorkerPool](indexer, apiv1alpha1.Resource("workerpool"))} +} + +// WorkerPools returns an object that can list and get WorkerPools. +func (s *workerPoolLister) WorkerPools(namespace string) WorkerPoolNamespaceLister { + return workerPoolNamespaceLister{listers.NewNamespaced[*apiv1alpha1.WorkerPool](s.ResourceIndexer, namespace)} +} + +// WorkerPoolNamespaceLister helps list and get WorkerPools. +// All objects returned here must be treated as read-only. +type WorkerPoolNamespaceLister interface { + // List lists all WorkerPools in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*apiv1alpha1.WorkerPool, err error) + // Get retrieves the WorkerPool from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*apiv1alpha1.WorkerPool, error) + WorkerPoolNamespaceListerExpansion +} + +// workerPoolNamespaceLister implements the WorkerPoolNamespaceLister +// interface. +type workerPoolNamespaceLister struct { + listers.ResourceIndexer[*apiv1alpha1.WorkerPool] +} diff --git a/proto/ateapipb/ateapi.pb.go b/proto/ateapipb/ateapi.pb.go new file mode 100644 index 000000000..1f3f67bb6 --- /dev/null +++ b/proto/ateapipb/ateapi.pb.go @@ -0,0 +1,1448 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// TODO: Here and everywhere, s/Session/Actor to align with the glossary. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11-devel +// protoc v4.25.3 +// source: ateapi.proto + +package ateapipb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Actor_Status int32 + +const ( + Actor_STATUS_UNSPECIFIED Actor_Status = 0 + Actor_STATUS_RESUMING Actor_Status = 1 + Actor_STATUS_RUNNING Actor_Status = 2 + Actor_STATUS_SUSPENDING Actor_Status = 3 + Actor_STATUS_SUSPENDED Actor_Status = 4 +) + +// Enum value maps for Actor_Status. +var ( + Actor_Status_name = map[int32]string{ + 0: "STATUS_UNSPECIFIED", + 1: "STATUS_RESUMING", + 2: "STATUS_RUNNING", + 3: "STATUS_SUSPENDING", + 4: "STATUS_SUSPENDED", + } + Actor_Status_value = map[string]int32{ + "STATUS_UNSPECIFIED": 0, + "STATUS_RESUMING": 1, + "STATUS_RUNNING": 2, + "STATUS_SUSPENDING": 3, + "STATUS_SUSPENDED": 4, + } +) + +func (x Actor_Status) Enum() *Actor_Status { + p := new(Actor_Status) + *p = x + return p +} + +func (x Actor_Status) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Actor_Status) Descriptor() protoreflect.EnumDescriptor { + return file_ateapi_proto_enumTypes[0].Descriptor() +} + +func (Actor_Status) Type() protoreflect.EnumType { + return &file_ateapi_proto_enumTypes[0] +} + +func (x Actor_Status) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Actor_Status.Descriptor instead. +func (Actor_Status) EnumDescriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{0, 0} +} + +type Actor struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + ActorTemplateNamespace string `protobuf:"bytes,3,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,4,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + Status Actor_Status `protobuf:"varint,5,opt,name=status,proto3,enum=ateapi.Actor_Status" json:"status,omitempty"` + AteomPodNamespace string `protobuf:"bytes,6,opt,name=ateom_pod_namespace,json=ateomPodNamespace,proto3" json:"ateom_pod_namespace,omitempty"` + AteomPodName string `protobuf:"bytes,7,opt,name=ateom_pod_name,json=ateomPodName,proto3" json:"ateom_pod_name,omitempty"` + AteomPodIp string `protobuf:"bytes,8,opt,name=ateom_pod_ip,json=ateomPodIp,proto3" json:"ateom_pod_ip,omitempty"` + LastSnapshot string `protobuf:"bytes,9,opt,name=last_snapshot,json=lastSnapshot,proto3" json:"last_snapshot,omitempty"` + InProgressSnapshot string `protobuf:"bytes,10,opt,name=in_progress_snapshot,json=inProgressSnapshot,proto3" json:"in_progress_snapshot,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Actor) Reset() { + *x = Actor{} + mi := &file_ateapi_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Actor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Actor) ProtoMessage() {} + +func (x *Actor) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Actor.ProtoReflect.Descriptor instead. +func (*Actor) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{0} +} + +func (x *Actor) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *Actor) GetVersion() int64 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *Actor) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *Actor) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *Actor) GetStatus() Actor_Status { + if x != nil { + return x.Status + } + return Actor_STATUS_UNSPECIFIED +} + +func (x *Actor) GetAteomPodNamespace() string { + if x != nil { + return x.AteomPodNamespace + } + return "" +} + +func (x *Actor) GetAteomPodName() string { + if x != nil { + return x.AteomPodName + } + return "" +} + +func (x *Actor) GetAteomPodIp() string { + if x != nil { + return x.AteomPodIp + } + return "" +} + +func (x *Actor) GetLastSnapshot() string { + if x != nil { + return x.LastSnapshot + } + return "" +} + +func (x *Actor) GetInProgressSnapshot() string { + if x != nil { + return x.InProgressSnapshot + } + return "" +} + +type GetActorRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetActorRequest) Reset() { + *x = GetActorRequest{} + mi := &file_ateapi_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetActorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetActorRequest) ProtoMessage() {} + +func (x *GetActorRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetActorRequest.ProtoReflect.Descriptor instead. +func (*GetActorRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{1} +} + +func (x *GetActorRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +type GetActorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Actor *Actor `protobuf:"bytes,1,opt,name=actor,proto3" json:"actor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetActorResponse) Reset() { + *x = GetActorResponse{} + mi := &file_ateapi_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetActorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetActorResponse) ProtoMessage() {} + +func (x *GetActorResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetActorResponse.ProtoReflect.Descriptor instead. +func (*GetActorResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{2} +} + +func (x *GetActorResponse) GetActor() *Actor { + if x != nil { + return x.Actor + } + return nil +} + +// Request to create a new Actor. +type CreateActorRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The custom identifier for the new Actor. Must be a valid DNS-1123 label. + ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + // The namespace of the ActorTemplate to derive from. + ActorTemplateNamespace string `protobuf:"bytes,2,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + // The name of the ActorTemplate to derive from. + ActorTemplateName string `protobuf:"bytes,3,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateActorRequest) Reset() { + *x = CreateActorRequest{} + mi := &file_ateapi_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateActorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateActorRequest) ProtoMessage() {} + +func (x *CreateActorRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateActorRequest.ProtoReflect.Descriptor instead. +func (*CreateActorRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateActorRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *CreateActorRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *CreateActorRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +type CreateActorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Actor *Actor `protobuf:"bytes,1,opt,name=actor,proto3" json:"actor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateActorResponse) Reset() { + *x = CreateActorResponse{} + mi := &file_ateapi_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateActorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateActorResponse) ProtoMessage() {} + +func (x *CreateActorResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateActorResponse.ProtoReflect.Descriptor instead. +func (*CreateActorResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{4} +} + +func (x *CreateActorResponse) GetActor() *Actor { + if x != nil { + return x.Actor + } + return nil +} + +type SuspendActorRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SuspendActorRequest) Reset() { + *x = SuspendActorRequest{} + mi := &file_ateapi_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SuspendActorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SuspendActorRequest) ProtoMessage() {} + +func (x *SuspendActorRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SuspendActorRequest.ProtoReflect.Descriptor instead. +func (*SuspendActorRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{5} +} + +func (x *SuspendActorRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +type SuspendActorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Actor *Actor `protobuf:"bytes,1,opt,name=actor,proto3" json:"actor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SuspendActorResponse) Reset() { + *x = SuspendActorResponse{} + mi := &file_ateapi_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SuspendActorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SuspendActorResponse) ProtoMessage() {} + +func (x *SuspendActorResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SuspendActorResponse.ProtoReflect.Descriptor instead. +func (*SuspendActorResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{6} +} + +func (x *SuspendActorResponse) GetActor() *Actor { + if x != nil { + return x.Actor + } + return nil +} + +type ResumeActorRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + // If true, skip golden snapshot and boot the workload from scratch. + Boot bool `protobuf:"varint,2,opt,name=boot,proto3" json:"boot,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResumeActorRequest) Reset() { + *x = ResumeActorRequest{} + mi := &file_ateapi_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResumeActorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResumeActorRequest) ProtoMessage() {} + +func (x *ResumeActorRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResumeActorRequest.ProtoReflect.Descriptor instead. +func (*ResumeActorRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{7} +} + +func (x *ResumeActorRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *ResumeActorRequest) GetBoot() bool { + if x != nil { + return x.Boot + } + return false +} + +type ResumeActorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Actor *Actor `protobuf:"bytes,1,opt,name=actor,proto3" json:"actor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResumeActorResponse) Reset() { + *x = ResumeActorResponse{} + mi := &file_ateapi_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResumeActorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResumeActorResponse) ProtoMessage() {} + +func (x *ResumeActorResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResumeActorResponse.ProtoReflect.Descriptor instead. +func (*ResumeActorResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{8} +} + +func (x *ResumeActorResponse) GetActor() *Actor { + if x != nil { + return x.Actor + } + return nil +} + +type DeleteActorRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteActorRequest) Reset() { + *x = DeleteActorRequest{} + mi := &file_ateapi_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteActorRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteActorRequest) ProtoMessage() {} + +func (x *DeleteActorRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteActorRequest.ProtoReflect.Descriptor instead. +func (*DeleteActorRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{9} +} + +func (x *DeleteActorRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +type DeleteActorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteActorResponse) Reset() { + *x = DeleteActorResponse{} + mi := &file_ateapi_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteActorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteActorResponse) ProtoMessage() {} + +func (x *DeleteActorResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteActorResponse.ProtoReflect.Descriptor instead. +func (*DeleteActorResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{10} +} + +type ListWorkersRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWorkersRequest) Reset() { + *x = ListWorkersRequest{} + mi := &file_ateapi_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWorkersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWorkersRequest) ProtoMessage() {} + +func (x *ListWorkersRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListWorkersRequest.ProtoReflect.Descriptor instead. +func (*ListWorkersRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{11} +} + +type ListWorkersResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Workers []*Worker `protobuf:"bytes,1,rep,name=workers,proto3" json:"workers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWorkersResponse) Reset() { + *x = ListWorkersResponse{} + mi := &file_ateapi_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWorkersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWorkersResponse) ProtoMessage() {} + +func (x *ListWorkersResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListWorkersResponse.ProtoReflect.Descriptor instead. +func (*ListWorkersResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{12} +} + +func (x *ListWorkersResponse) GetWorkers() []*Worker { + if x != nil { + return x.Workers + } + return nil +} + +type ListActorsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListActorsRequest) Reset() { + *x = ListActorsRequest{} + mi := &file_ateapi_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListActorsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListActorsRequest) ProtoMessage() {} + +func (x *ListActorsRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListActorsRequest.ProtoReflect.Descriptor instead. +func (*ListActorsRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{13} +} + +type ListActorsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Actors []*Actor `protobuf:"bytes,1,rep,name=actors,proto3" json:"actors,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListActorsResponse) Reset() { + *x = ListActorsResponse{} + mi := &file_ateapi_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListActorsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListActorsResponse) ProtoMessage() {} + +func (x *ListActorsResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListActorsResponse.ProtoReflect.Descriptor instead. +func (*ListActorsResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{14} +} + +func (x *ListActorsResponse) GetActors() []*Actor { + if x != nil { + return x.Actors + } + return nil +} + +type Worker struct { + state protoimpl.MessageState `protogen:"open.v1"` + WorkerNamespace string `protobuf:"bytes,1,opt,name=worker_namespace,json=workerNamespace,proto3" json:"worker_namespace,omitempty"` + WorkerPool string `protobuf:"bytes,2,opt,name=worker_pool,json=workerPool,proto3" json:"worker_pool,omitempty"` + WorkerPod string `protobuf:"bytes,3,opt,name=worker_pod,json=workerPod,proto3" json:"worker_pod,omitempty"` + ActorNamespace string `protobuf:"bytes,4,opt,name=actor_namespace,json=actorNamespace,proto3" json:"actor_namespace,omitempty"` + ActorTemplate string `protobuf:"bytes,5,opt,name=actor_template,json=actorTemplate,proto3" json:"actor_template,omitempty"` + ActorId string `protobuf:"bytes,6,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + Ip string `protobuf:"bytes,7,opt,name=ip,proto3" json:"ip,omitempty"` + Version int64 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Worker) Reset() { + *x = Worker{} + mi := &file_ateapi_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Worker) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Worker) ProtoMessage() {} + +func (x *Worker) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Worker.ProtoReflect.Descriptor instead. +func (*Worker) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{15} +} + +func (x *Worker) GetWorkerNamespace() string { + if x != nil { + return x.WorkerNamespace + } + return "" +} + +func (x *Worker) GetWorkerPool() string { + if x != nil { + return x.WorkerPool + } + return "" +} + +func (x *Worker) GetWorkerPod() string { + if x != nil { + return x.WorkerPod + } + return "" +} + +func (x *Worker) GetActorNamespace() string { + if x != nil { + return x.ActorNamespace + } + return "" +} + +func (x *Worker) GetActorTemplate() string { + if x != nil { + return x.ActorTemplate + } + return "" +} + +func (x *Worker) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *Worker) GetIp() string { + if x != nil { + return x.Ip + } + return "" +} + +func (x *Worker) GetVersion() int64 { + if x != nil { + return x.Version + } + return 0 +} + +type DebugClearRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DebugClearRequest) Reset() { + *x = DebugClearRequest{} + mi := &file_ateapi_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DebugClearRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DebugClearRequest) ProtoMessage() {} + +func (x *DebugClearRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DebugClearRequest.ProtoReflect.Descriptor instead. +func (*DebugClearRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{16} +} + +type DebugClearResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DebugClearResponse) Reset() { + *x = DebugClearResponse{} + mi := &file_ateapi_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DebugClearResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DebugClearResponse) ProtoMessage() {} + +func (x *DebugClearResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DebugClearResponse.ProtoReflect.Descriptor instead. +func (*DebugClearResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{17} +} + +type MintJWTRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Audience []string `protobuf:"bytes,1,rep,name=audience,proto3" json:"audience,omitempty"` + AppId string `protobuf:"bytes,2,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"` + UserId string `protobuf:"bytes,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SessionId string `protobuf:"bytes,4,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MintJWTRequest) Reset() { + *x = MintJWTRequest{} + mi := &file_ateapi_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MintJWTRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MintJWTRequest) ProtoMessage() {} + +func (x *MintJWTRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MintJWTRequest.ProtoReflect.Descriptor instead. +func (*MintJWTRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{18} +} + +func (x *MintJWTRequest) GetAudience() []string { + if x != nil { + return x.Audience + } + return nil +} + +func (x *MintJWTRequest) GetAppId() string { + if x != nil { + return x.AppId + } + return "" +} + +func (x *MintJWTRequest) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *MintJWTRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type MintJWTResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Session JWT. An OIDC Discovery-compatible JWT + // + // Claims: + // + // - iss: Issuer - a valid URL where a relying party can fetch the OIDC + // discovery documents. + // - sub: Subject - a string expressing the identity carried in the + // + // credential. Format + // + // `app/${appid}/user/${userid}/session/${sessionid}`. + // - aud: Audience - a string identifying the service this token will be used + // to authenticate to. + // - nbf: Not Before - a numeric unix timestamp + // - exp: Expiration - a numeric unix timestamp + // - iat: Issued At - a numeric unix timestamp + // - `ate.dev`: Ate/Substrate Extension - JSON object + // - appID: (string) The Substrate App ID + // - userID: (string) The Substrate User ID + // - sessionID: (string) The Substrate Session ID + SessionJwt string `protobuf:"bytes,1,opt,name=session_jwt,json=sessionJwt,proto3" json:"session_jwt,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MintJWTResponse) Reset() { + *x = MintJWTResponse{} + mi := &file_ateapi_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MintJWTResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MintJWTResponse) ProtoMessage() {} + +func (x *MintJWTResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MintJWTResponse.ProtoReflect.Descriptor instead. +func (*MintJWTResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{19} +} + +func (x *MintJWTResponse) GetSessionJwt() string { + if x != nil { + return x.SessionJwt + } + return "" +} + +type MintCertRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + AppId string `protobuf:"bytes,1,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"` + UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + // Request contains DER encoded bytes of a x509 certificate signing request. + // The signer will ignore the contents of the CSR except to extract the + // subject public key. + CertificateSigningRequest []byte `protobuf:"bytes,4,opt,name=certificate_signing_request,json=certificateSigningRequest,proto3" json:"certificate_signing_request,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MintCertRequest) Reset() { + *x = MintCertRequest{} + mi := &file_ateapi_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MintCertRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MintCertRequest) ProtoMessage() {} + +func (x *MintCertRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MintCertRequest.ProtoReflect.Descriptor instead. +func (*MintCertRequest) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{20} +} + +func (x *MintCertRequest) GetAppId() string { + if x != nil { + return x.AppId + } + return "" +} + +func (x *MintCertRequest) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *MintCertRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *MintCertRequest) GetCertificateSigningRequest() []byte { + if x != nil { + return x.CertificateSigningRequest + } + return nil +} + +type MintCertResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Response contains a list of DER encoded certificates. The first entry is the + // leaf certificate, and any remaining entries are intermediates in + // leaf-to-root order. + SessionCertificates [][]byte `protobuf:"bytes,1,rep,name=session_certificates,json=sessionCertificates,proto3" json:"session_certificates,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MintCertResponse) Reset() { + *x = MintCertResponse{} + mi := &file_ateapi_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MintCertResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MintCertResponse) ProtoMessage() {} + +func (x *MintCertResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MintCertResponse.ProtoReflect.Descriptor instead. +func (*MintCertResponse) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{21} +} + +func (x *MintCertResponse) GetSessionCertificates() [][]byte { + if x != nil { + return x.SessionCertificates + } + return nil +} + +var File_ateapi_proto protoreflect.FileDescriptor + +const file_ateapi_proto_rawDesc = "" + + "\n" + + "\fateapi.proto\x12\x06ateapi\"\x9b\x04\n" + + "\x05Actor\x12\x19\n" + + "\bactor_id\x18\x01 \x01(\tR\aactorId\x12\x18\n" + + "\aversion\x18\x02 \x01(\x03R\aversion\x128\n" + + "\x18actor_template_namespace\x18\x03 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x04 \x01(\tR\x11actorTemplateName\x12,\n" + + "\x06status\x18\x05 \x01(\x0e2\x14.ateapi.Actor.StatusR\x06status\x12.\n" + + "\x13ateom_pod_namespace\x18\x06 \x01(\tR\x11ateomPodNamespace\x12$\n" + + "\x0eateom_pod_name\x18\a \x01(\tR\fateomPodName\x12 \n" + + "\fateom_pod_ip\x18\b \x01(\tR\n" + + "ateomPodIp\x12#\n" + + "\rlast_snapshot\x18\t \x01(\tR\flastSnapshot\x120\n" + + "\x14in_progress_snapshot\x18\n" + + " \x01(\tR\x12inProgressSnapshot\"v\n" + + "\x06Status\x12\x16\n" + + "\x12STATUS_UNSPECIFIED\x10\x00\x12\x13\n" + + "\x0fSTATUS_RESUMING\x10\x01\x12\x12\n" + + "\x0eSTATUS_RUNNING\x10\x02\x12\x15\n" + + "\x11STATUS_SUSPENDING\x10\x03\x12\x14\n" + + "\x10STATUS_SUSPENDED\x10\x04\",\n" + + "\x0fGetActorRequest\x12\x19\n" + + "\bactor_id\x18\x01 \x01(\tR\aactorId\"7\n" + + "\x10GetActorResponse\x12#\n" + + "\x05actor\x18\x01 \x01(\v2\r.ateapi.ActorR\x05actor\"\x99\x01\n" + + "\x12CreateActorRequest\x12\x19\n" + + "\bactor_id\x18\x01 \x01(\tR\aactorId\x128\n" + + "\x18actor_template_namespace\x18\x02 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x03 \x01(\tR\x11actorTemplateName\":\n" + + "\x13CreateActorResponse\x12#\n" + + "\x05actor\x18\x01 \x01(\v2\r.ateapi.ActorR\x05actor\"0\n" + + "\x13SuspendActorRequest\x12\x19\n" + + "\bactor_id\x18\x01 \x01(\tR\aactorId\";\n" + + "\x14SuspendActorResponse\x12#\n" + + "\x05actor\x18\x01 \x01(\v2\r.ateapi.ActorR\x05actor\"C\n" + + "\x12ResumeActorRequest\x12\x19\n" + + "\bactor_id\x18\x01 \x01(\tR\aactorId\x12\x12\n" + + "\x04boot\x18\x02 \x01(\bR\x04boot\":\n" + + "\x13ResumeActorResponse\x12#\n" + + "\x05actor\x18\x01 \x01(\v2\r.ateapi.ActorR\x05actor\"/\n" + + "\x12DeleteActorRequest\x12\x19\n" + + "\bactor_id\x18\x01 \x01(\tR\aactorId\"\x15\n" + + "\x13DeleteActorResponse\"\x14\n" + + "\x12ListWorkersRequest\"?\n" + + "\x13ListWorkersResponse\x12(\n" + + "\aworkers\x18\x01 \x03(\v2\x0e.ateapi.WorkerR\aworkers\"\x13\n" + + "\x11ListActorsRequest\";\n" + + "\x12ListActorsResponse\x12%\n" + + "\x06actors\x18\x01 \x03(\v2\r.ateapi.ActorR\x06actors\"\x88\x02\n" + + "\x06Worker\x12)\n" + + "\x10worker_namespace\x18\x01 \x01(\tR\x0fworkerNamespace\x12\x1f\n" + + "\vworker_pool\x18\x02 \x01(\tR\n" + + "workerPool\x12\x1d\n" + + "\n" + + "worker_pod\x18\x03 \x01(\tR\tworkerPod\x12'\n" + + "\x0factor_namespace\x18\x04 \x01(\tR\x0eactorNamespace\x12%\n" + + "\x0eactor_template\x18\x05 \x01(\tR\ractorTemplate\x12\x19\n" + + "\bactor_id\x18\x06 \x01(\tR\aactorId\x12\x0e\n" + + "\x02ip\x18\a \x01(\tR\x02ip\x12\x18\n" + + "\aversion\x18\b \x01(\x03R\aversion\"\x13\n" + + "\x11DebugClearRequest\"\x14\n" + + "\x12DebugClearResponse\"{\n" + + "\x0eMintJWTRequest\x12\x1a\n" + + "\baudience\x18\x01 \x03(\tR\baudience\x12\x15\n" + + "\x06app_id\x18\x02 \x01(\tR\x05appId\x12\x17\n" + + "\auser_id\x18\x03 \x01(\tR\x06userId\x12\x1d\n" + + "\n" + + "session_id\x18\x04 \x01(\tR\tsessionId\"2\n" + + "\x0fMintJWTResponse\x12\x1f\n" + + "\vsession_jwt\x18\x01 \x01(\tR\n" + + "sessionJwt\"\xa0\x01\n" + + "\x0fMintCertRequest\x12\x15\n" + + "\x06app_id\x18\x01 \x01(\tR\x05appId\x12\x17\n" + + "\auser_id\x18\x02 \x01(\tR\x06userId\x12\x1d\n" + + "\n" + + "session_id\x18\x03 \x01(\tR\tsessionId\x12>\n" + + "\x1bcertificate_signing_request\x18\x04 \x01(\fR\x19certificateSigningRequest\"E\n" + + "\x10MintCertResponse\x121\n" + + "\x14session_certificates\x18\x01 \x03(\fR\x13sessionCertificates2\xcd\x04\n" + + "\aControl\x12?\n" + + "\bGetActor\x12\x17.ateapi.GetActorRequest\x1a\x18.ateapi.GetActorResponse\"\x00\x12H\n" + + "\vCreateActor\x12\x1a.ateapi.CreateActorRequest\x1a\x1b.ateapi.CreateActorResponse\"\x00\x12K\n" + + "\fSuspendActor\x12\x1b.ateapi.SuspendActorRequest\x1a\x1c.ateapi.SuspendActorResponse\"\x00\x12H\n" + + "\vResumeActor\x12\x1a.ateapi.ResumeActorRequest\x1a\x1b.ateapi.ResumeActorResponse\"\x00\x12H\n" + + "\vDeleteActor\x12\x1a.ateapi.DeleteActorRequest\x1a\x1b.ateapi.DeleteActorResponse\"\x00\x12H\n" + + "\vListWorkers\x12\x1a.ateapi.ListWorkersRequest\x1a\x1b.ateapi.ListWorkersResponse\"\x00\x12E\n" + + "\n" + + "ListActors\x12\x19.ateapi.ListActorsRequest\x1a\x1a.ateapi.ListActorsResponse\"\x00\x12E\n" + + "\n" + + "DebugClear\x12\x19.ateapi.DebugClearRequest\x1a\x1a.ateapi.DebugClearResponse\"\x002\x8c\x01\n" + + "\x0fSessionIdentity\x12:\n" + + "\aMintJWT\x12\x16.ateapi.MintJWTRequest\x1a\x17.ateapi.MintJWTResponse\x12=\n" + + "\bMintCert\x12\x17.ateapi.MintCertRequest\x1a\x18.ateapi.MintCertResponseB5Z3github.com/agent-substrate/substrate/proto/ateapipbb\x06proto3" + +var ( + file_ateapi_proto_rawDescOnce sync.Once + file_ateapi_proto_rawDescData []byte +) + +func file_ateapi_proto_rawDescGZIP() []byte { + file_ateapi_proto_rawDescOnce.Do(func() { + file_ateapi_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ateapi_proto_rawDesc), len(file_ateapi_proto_rawDesc))) + }) + return file_ateapi_proto_rawDescData +} + +var file_ateapi_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_ateapi_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_ateapi_proto_goTypes = []any{ + (Actor_Status)(0), // 0: ateapi.Actor.Status + (*Actor)(nil), // 1: ateapi.Actor + (*GetActorRequest)(nil), // 2: ateapi.GetActorRequest + (*GetActorResponse)(nil), // 3: ateapi.GetActorResponse + (*CreateActorRequest)(nil), // 4: ateapi.CreateActorRequest + (*CreateActorResponse)(nil), // 5: ateapi.CreateActorResponse + (*SuspendActorRequest)(nil), // 6: ateapi.SuspendActorRequest + (*SuspendActorResponse)(nil), // 7: ateapi.SuspendActorResponse + (*ResumeActorRequest)(nil), // 8: ateapi.ResumeActorRequest + (*ResumeActorResponse)(nil), // 9: ateapi.ResumeActorResponse + (*DeleteActorRequest)(nil), // 10: ateapi.DeleteActorRequest + (*DeleteActorResponse)(nil), // 11: ateapi.DeleteActorResponse + (*ListWorkersRequest)(nil), // 12: ateapi.ListWorkersRequest + (*ListWorkersResponse)(nil), // 13: ateapi.ListWorkersResponse + (*ListActorsRequest)(nil), // 14: ateapi.ListActorsRequest + (*ListActorsResponse)(nil), // 15: ateapi.ListActorsResponse + (*Worker)(nil), // 16: ateapi.Worker + (*DebugClearRequest)(nil), // 17: ateapi.DebugClearRequest + (*DebugClearResponse)(nil), // 18: ateapi.DebugClearResponse + (*MintJWTRequest)(nil), // 19: ateapi.MintJWTRequest + (*MintJWTResponse)(nil), // 20: ateapi.MintJWTResponse + (*MintCertRequest)(nil), // 21: ateapi.MintCertRequest + (*MintCertResponse)(nil), // 22: ateapi.MintCertResponse +} +var file_ateapi_proto_depIdxs = []int32{ + 0, // 0: ateapi.Actor.status:type_name -> ateapi.Actor.Status + 1, // 1: ateapi.GetActorResponse.actor:type_name -> ateapi.Actor + 1, // 2: ateapi.CreateActorResponse.actor:type_name -> ateapi.Actor + 1, // 3: ateapi.SuspendActorResponse.actor:type_name -> ateapi.Actor + 1, // 4: ateapi.ResumeActorResponse.actor:type_name -> ateapi.Actor + 16, // 5: ateapi.ListWorkersResponse.workers:type_name -> ateapi.Worker + 1, // 6: ateapi.ListActorsResponse.actors:type_name -> ateapi.Actor + 2, // 7: ateapi.Control.GetActor:input_type -> ateapi.GetActorRequest + 4, // 8: ateapi.Control.CreateActor:input_type -> ateapi.CreateActorRequest + 6, // 9: ateapi.Control.SuspendActor:input_type -> ateapi.SuspendActorRequest + 8, // 10: ateapi.Control.ResumeActor:input_type -> ateapi.ResumeActorRequest + 10, // 11: ateapi.Control.DeleteActor:input_type -> ateapi.DeleteActorRequest + 12, // 12: ateapi.Control.ListWorkers:input_type -> ateapi.ListWorkersRequest + 14, // 13: ateapi.Control.ListActors:input_type -> ateapi.ListActorsRequest + 17, // 14: ateapi.Control.DebugClear:input_type -> ateapi.DebugClearRequest + 19, // 15: ateapi.SessionIdentity.MintJWT:input_type -> ateapi.MintJWTRequest + 21, // 16: ateapi.SessionIdentity.MintCert:input_type -> ateapi.MintCertRequest + 3, // 17: ateapi.Control.GetActor:output_type -> ateapi.GetActorResponse + 5, // 18: ateapi.Control.CreateActor:output_type -> ateapi.CreateActorResponse + 7, // 19: ateapi.Control.SuspendActor:output_type -> ateapi.SuspendActorResponse + 9, // 20: ateapi.Control.ResumeActor:output_type -> ateapi.ResumeActorResponse + 11, // 21: ateapi.Control.DeleteActor:output_type -> ateapi.DeleteActorResponse + 13, // 22: ateapi.Control.ListWorkers:output_type -> ateapi.ListWorkersResponse + 15, // 23: ateapi.Control.ListActors:output_type -> ateapi.ListActorsResponse + 18, // 24: ateapi.Control.DebugClear:output_type -> ateapi.DebugClearResponse + 20, // 25: ateapi.SessionIdentity.MintJWT:output_type -> ateapi.MintJWTResponse + 22, // 26: ateapi.SessionIdentity.MintCert:output_type -> ateapi.MintCertResponse + 17, // [17:27] is the sub-list for method output_type + 7, // [7:17] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_ateapi_proto_init() } +func file_ateapi_proto_init() { + if File_ateapi_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_ateapi_proto_rawDesc), len(file_ateapi_proto_rawDesc)), + NumEnums: 1, + NumMessages: 22, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_ateapi_proto_goTypes, + DependencyIndexes: file_ateapi_proto_depIdxs, + EnumInfos: file_ateapi_proto_enumTypes, + MessageInfos: file_ateapi_proto_msgTypes, + }.Build() + File_ateapi_proto = out.File + file_ateapi_proto_goTypes = nil + file_ateapi_proto_depIdxs = nil +} diff --git a/proto/ateapipb/ateapi.proto b/proto/ateapipb/ateapi.proto new file mode 100644 index 000000000..b157599e5 --- /dev/null +++ b/proto/ateapipb/ateapi.proto @@ -0,0 +1,226 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// TODO: Here and everywhere, s/Session/Actor to align with the glossary. + +syntax = "proto3"; + +package ateapi; + +option go_package = "github.com/agent-substrate/substrate/proto/ateapipb"; + + +// Control is the primary RPC interface for Agentic Substrate. +service Control { + // Get an Actor. + rpc GetActor(GetActorRequest) returns (GetActorResponse) {} + + // Create a new Actor deriving from a given ActorTemplate. + rpc CreateActor(CreateActorRequest) returns (CreateActorResponse) {} + + // Suspend a given actor to a new snapshot. + rpc SuspendActor(SuspendActorRequest) returns (SuspendActorResponse) {} + + // Resume an actor from its latest snapshot. + rpc ResumeActor(ResumeActorRequest) returns (ResumeActorResponse) {} + + // Delete an actor. Only suspended actors can be deleted. + rpc DeleteActor(DeleteActorRequest) returns (DeleteActorResponse) {} + + // List all workers currently reflected in redis. + rpc ListWorkers(ListWorkersRequest) returns (ListWorkersResponse) {} + + // List all actors currently reflected in redis. + rpc ListActors(ListActorsRequest) returns (ListActorsResponse) {} + + // Debugging: drop all data from the ate database. + rpc DebugClear(DebugClearRequest) returns (DebugClearResponse) {} +} + +message Actor { + string actor_id = 1; + int64 version = 2; + + string actor_template_namespace = 3; + string actor_template_name = 4; + + enum Status { + STATUS_UNSPECIFIED = 0; + STATUS_RESUMING = 1; + STATUS_RUNNING = 2; + STATUS_SUSPENDING = 3; + STATUS_SUSPENDED = 4; + } + Status status = 5; + + string ateom_pod_namespace = 6; + string ateom_pod_name = 7; + string ateom_pod_ip = 8; + + string last_snapshot = 9; + string in_progress_snapshot = 10; +} + +message GetActorRequest { + string actor_id = 1; +} + +message GetActorResponse { + Actor actor = 1; +} + +// Request to create a new Actor. +message CreateActorRequest { + // The custom identifier for the new Actor. Must be a valid DNS-1123 label. + string actor_id = 1; + + // The namespace of the ActorTemplate to derive from. + string actor_template_namespace = 2; + + // The name of the ActorTemplate to derive from. + string actor_template_name = 3; +} + +message CreateActorResponse { + Actor actor = 1; +} + +message SuspendActorRequest { + string actor_id = 1; +} + +message SuspendActorResponse { + Actor actor = 1; +} + +message ResumeActorRequest { + string actor_id = 1; + + // If true, skip golden snapshot and boot the workload from scratch. + bool boot = 2; +} + +message ResumeActorResponse { + Actor actor = 1; +} + +message DeleteActorRequest { + string actor_id = 1; +} + +message DeleteActorResponse {} + +message ListWorkersRequest {} + +message ListWorkersResponse { + repeated Worker workers = 1; +} + +message ListActorsRequest {} + +message ListActorsResponse { + repeated Actor actors = 1; +} + +message Worker { + string worker_namespace = 1; + string worker_pool = 2; + string worker_pod = 3; + + string actor_namespace = 4; + string actor_template = 5; + string actor_id = 6; + string ip = 7; + int64 version = 8; +} + +message DebugClearRequest {} + +message DebugClearResponse {} + +// SessionIdentity allows substrate workloads to exchange their +// infrastructure-level credentials (k8s service account token, etc.) for a +// substrate session-level credential. A given substrate session might migrate +// between many different physical workers over the course of its lifecycle, +// whereas the session credential's identity will be stable for the life of the +// session. +// +// This service requires authentication. You can authenticate with a Kubernetes +// service account token in an `Authorization: Bearer` header, or you can +// authenticate with a Kubernetes service account certificate as an mTLS +// certificate. (Kubernetes service account certificates do not currently exist +// upstream, but we will provide a polyfill based on Pod Certificates). +// +// The broker will check that the service credentials you authenticated with +// belong to a Pod that is currently mapped to the requested session in the +// session database. +service SessionIdentity { + // Request a Session Identity JWT. + // + // To call this RPC, you must be authenticated as the Kubernetes Pod that is + // currently running the requested session. + rpc MintJWT(MintJWTRequest) returns (MintJWTResponse); + + // Request a Session Identity Certificate. To call this RPC, you must have + // authenticated with a client certificate, not a bearer token. + rpc MintCert(MintCertRequest) returns (MintCertResponse); +} + +message MintJWTRequest { + repeated string audience = 1; + + string app_id = 2; + string user_id = 3; + string session_id = 4; +} + +message MintJWTResponse { + // Session JWT. An OIDC Discovery-compatible JWT + // + // Claims: + // + // * iss: Issuer - a valid URL where a relying party can fetch the OIDC + // discovery documents. + // * sub: Subject - a string expressing the identity carried in the + // credential. Format + // `app/${appid}/user/${userid}/session/${sessionid}`. + // * aud: Audience - a string identifying the service this token will be used + // to authenticate to. + // * nbf: Not Before - a numeric unix timestamp + // * exp: Expiration - a numeric unix timestamp + // * iat: Issued At - a numeric unix timestamp + // * `ate.dev`: Ate/Substrate Extension - JSON object + // * appID: (string) The Substrate App ID + // * userID: (string) The Substrate User ID + // * sessionID: (string) The Substrate Session ID + string session_jwt = 1; +} + +message MintCertRequest { + string app_id = 1; + string user_id = 2; + string session_id = 3; + + // Request contains DER encoded bytes of a x509 certificate signing request. + // The signer will ignore the contents of the CSR except to extract the + // subject public key. + bytes certificate_signing_request = 4; +} + +message MintCertResponse { + // Response contains a list of DER encoded certificates. The first entry is the + // leaf certificate, and any remaining entries are intermediates in + // leaf-to-root order. + repeated bytes session_certificates = 1; +} diff --git a/proto/ateapipb/ateapi_grpc.pb.go b/proto/ateapipb/ateapi_grpc.pb.go new file mode 100644 index 000000000..5b55f3da4 --- /dev/null +++ b/proto/ateapipb/ateapi_grpc.pb.go @@ -0,0 +1,609 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// TODO: Here and everywhere, s/Session/Actor to align with the glossary. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v4.25.3 +// source: ateapi.proto + +package ateapipb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Control_GetActor_FullMethodName = "/ateapi.Control/GetActor" + Control_CreateActor_FullMethodName = "/ateapi.Control/CreateActor" + Control_SuspendActor_FullMethodName = "/ateapi.Control/SuspendActor" + Control_ResumeActor_FullMethodName = "/ateapi.Control/ResumeActor" + Control_DeleteActor_FullMethodName = "/ateapi.Control/DeleteActor" + Control_ListWorkers_FullMethodName = "/ateapi.Control/ListWorkers" + Control_ListActors_FullMethodName = "/ateapi.Control/ListActors" + Control_DebugClear_FullMethodName = "/ateapi.Control/DebugClear" +) + +// ControlClient is the client API for Control service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// Control is the primary RPC interface for Agentic Substrate. +type ControlClient interface { + // Get an Actor. + GetActor(ctx context.Context, in *GetActorRequest, opts ...grpc.CallOption) (*GetActorResponse, error) + // Create a new Actor deriving from a given ActorTemplate. + CreateActor(ctx context.Context, in *CreateActorRequest, opts ...grpc.CallOption) (*CreateActorResponse, error) + // Suspend a given actor to a new snapshot. + SuspendActor(ctx context.Context, in *SuspendActorRequest, opts ...grpc.CallOption) (*SuspendActorResponse, error) + // Resume an actor from its latest snapshot. + ResumeActor(ctx context.Context, in *ResumeActorRequest, opts ...grpc.CallOption) (*ResumeActorResponse, error) + // Delete an actor. Only suspended actors can be deleted. + DeleteActor(ctx context.Context, in *DeleteActorRequest, opts ...grpc.CallOption) (*DeleteActorResponse, error) + // List all workers currently reflected in redis. + ListWorkers(ctx context.Context, in *ListWorkersRequest, opts ...grpc.CallOption) (*ListWorkersResponse, error) + // List all actors currently reflected in redis. + ListActors(ctx context.Context, in *ListActorsRequest, opts ...grpc.CallOption) (*ListActorsResponse, error) + // Debugging: drop all data from the ate database. + DebugClear(ctx context.Context, in *DebugClearRequest, opts ...grpc.CallOption) (*DebugClearResponse, error) +} + +type controlClient struct { + cc grpc.ClientConnInterface +} + +func NewControlClient(cc grpc.ClientConnInterface) ControlClient { + return &controlClient{cc} +} + +func (c *controlClient) GetActor(ctx context.Context, in *GetActorRequest, opts ...grpc.CallOption) (*GetActorResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetActorResponse) + err := c.cc.Invoke(ctx, Control_GetActor_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) CreateActor(ctx context.Context, in *CreateActorRequest, opts ...grpc.CallOption) (*CreateActorResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateActorResponse) + err := c.cc.Invoke(ctx, Control_CreateActor_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) SuspendActor(ctx context.Context, in *SuspendActorRequest, opts ...grpc.CallOption) (*SuspendActorResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SuspendActorResponse) + err := c.cc.Invoke(ctx, Control_SuspendActor_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) ResumeActor(ctx context.Context, in *ResumeActorRequest, opts ...grpc.CallOption) (*ResumeActorResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ResumeActorResponse) + err := c.cc.Invoke(ctx, Control_ResumeActor_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) DeleteActor(ctx context.Context, in *DeleteActorRequest, opts ...grpc.CallOption) (*DeleteActorResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteActorResponse) + err := c.cc.Invoke(ctx, Control_DeleteActor_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) ListWorkers(ctx context.Context, in *ListWorkersRequest, opts ...grpc.CallOption) (*ListWorkersResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWorkersResponse) + err := c.cc.Invoke(ctx, Control_ListWorkers_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) ListActors(ctx context.Context, in *ListActorsRequest, opts ...grpc.CallOption) (*ListActorsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListActorsResponse) + err := c.cc.Invoke(ctx, Control_ListActors_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) DebugClear(ctx context.Context, in *DebugClearRequest, opts ...grpc.CallOption) (*DebugClearResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DebugClearResponse) + err := c.cc.Invoke(ctx, Control_DebugClear_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ControlServer is the server API for Control service. +// All implementations must embed UnimplementedControlServer +// for forward compatibility. +// +// Control is the primary RPC interface for Agentic Substrate. +type ControlServer interface { + // Get an Actor. + GetActor(context.Context, *GetActorRequest) (*GetActorResponse, error) + // Create a new Actor deriving from a given ActorTemplate. + CreateActor(context.Context, *CreateActorRequest) (*CreateActorResponse, error) + // Suspend a given actor to a new snapshot. + SuspendActor(context.Context, *SuspendActorRequest) (*SuspendActorResponse, error) + // Resume an actor from its latest snapshot. + ResumeActor(context.Context, *ResumeActorRequest) (*ResumeActorResponse, error) + // Delete an actor. Only suspended actors can be deleted. + DeleteActor(context.Context, *DeleteActorRequest) (*DeleteActorResponse, error) + // List all workers currently reflected in redis. + ListWorkers(context.Context, *ListWorkersRequest) (*ListWorkersResponse, error) + // List all actors currently reflected in redis. + ListActors(context.Context, *ListActorsRequest) (*ListActorsResponse, error) + // Debugging: drop all data from the ate database. + DebugClear(context.Context, *DebugClearRequest) (*DebugClearResponse, error) + mustEmbedUnimplementedControlServer() +} + +// UnimplementedControlServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedControlServer struct{} + +func (UnimplementedControlServer) GetActor(context.Context, *GetActorRequest) (*GetActorResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetActor not implemented") +} +func (UnimplementedControlServer) CreateActor(context.Context, *CreateActorRequest) (*CreateActorResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CreateActor not implemented") +} +func (UnimplementedControlServer) SuspendActor(context.Context, *SuspendActorRequest) (*SuspendActorResponse, error) { + return nil, status.Error(codes.Unimplemented, "method SuspendActor not implemented") +} +func (UnimplementedControlServer) ResumeActor(context.Context, *ResumeActorRequest) (*ResumeActorResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ResumeActor not implemented") +} +func (UnimplementedControlServer) DeleteActor(context.Context, *DeleteActorRequest) (*DeleteActorResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteActor not implemented") +} +func (UnimplementedControlServer) ListWorkers(context.Context, *ListWorkersRequest) (*ListWorkersResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWorkers not implemented") +} +func (UnimplementedControlServer) ListActors(context.Context, *ListActorsRequest) (*ListActorsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListActors not implemented") +} +func (UnimplementedControlServer) DebugClear(context.Context, *DebugClearRequest) (*DebugClearResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DebugClear not implemented") +} +func (UnimplementedControlServer) mustEmbedUnimplementedControlServer() {} +func (UnimplementedControlServer) testEmbeddedByValue() {} + +// UnsafeControlServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ControlServer will +// result in compilation errors. +type UnsafeControlServer interface { + mustEmbedUnimplementedControlServer() +} + +func RegisterControlServer(s grpc.ServiceRegistrar, srv ControlServer) { + // If the following call panics, it indicates UnimplementedControlServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Control_ServiceDesc, srv) +} + +func _Control_GetActor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetActorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).GetActor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_GetActor_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).GetActor(ctx, req.(*GetActorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_CreateActor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateActorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).CreateActor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_CreateActor_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).CreateActor(ctx, req.(*CreateActorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_SuspendActor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SuspendActorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).SuspendActor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_SuspendActor_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).SuspendActor(ctx, req.(*SuspendActorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_ResumeActor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResumeActorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).ResumeActor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_ResumeActor_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).ResumeActor(ctx, req.(*ResumeActorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_DeleteActor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteActorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).DeleteActor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_DeleteActor_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).DeleteActor(ctx, req.(*DeleteActorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_ListWorkers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWorkersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).ListWorkers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_ListWorkers_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).ListWorkers(ctx, req.(*ListWorkersRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_ListActors_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListActorsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).ListActors(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_ListActors_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).ListActors(ctx, req.(*ListActorsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_DebugClear_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DebugClearRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).DebugClear(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_DebugClear_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).DebugClear(ctx, req.(*DebugClearRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Control_ServiceDesc is the grpc.ServiceDesc for Control service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Control_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ateapi.Control", + HandlerType: (*ControlServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetActor", + Handler: _Control_GetActor_Handler, + }, + { + MethodName: "CreateActor", + Handler: _Control_CreateActor_Handler, + }, + { + MethodName: "SuspendActor", + Handler: _Control_SuspendActor_Handler, + }, + { + MethodName: "ResumeActor", + Handler: _Control_ResumeActor_Handler, + }, + { + MethodName: "DeleteActor", + Handler: _Control_DeleteActor_Handler, + }, + { + MethodName: "ListWorkers", + Handler: _Control_ListWorkers_Handler, + }, + { + MethodName: "ListActors", + Handler: _Control_ListActors_Handler, + }, + { + MethodName: "DebugClear", + Handler: _Control_DebugClear_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ateapi.proto", +} + +const ( + SessionIdentity_MintJWT_FullMethodName = "/ateapi.SessionIdentity/MintJWT" + SessionIdentity_MintCert_FullMethodName = "/ateapi.SessionIdentity/MintCert" +) + +// SessionIdentityClient is the client API for SessionIdentity service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// SessionIdentity allows substrate workloads to exchange their +// infrastructure-level credentials (k8s service account token, etc.) for a +// substrate session-level credential. A given substrate session might migrate +// between many different physical workers over the course of its lifecycle, +// whereas the session credential's identity will be stable for the life of the +// session. +// +// This service requires authentication. You can authenticate with a Kubernetes +// service account token in an `Authorization: Bearer` header, or you can +// authenticate with a Kubernetes service account certificate as an mTLS +// certificate. (Kubernetes service account certificates do not currently exist +// upstream, but we will provide a polyfill based on Pod Certificates). +// +// The broker will check that the service credentials you authenticated with +// belong to a Pod that is currently mapped to the requested session in the +// session database. +type SessionIdentityClient interface { + // Request a Session Identity JWT. + // + // To call this RPC, you must be authenticated as the Kubernetes Pod that is + // currently running the requested session. + MintJWT(ctx context.Context, in *MintJWTRequest, opts ...grpc.CallOption) (*MintJWTResponse, error) + // Request a Session Identity Certificate. To call this RPC, you must have + // authenticated with a client certificate, not a bearer token. + MintCert(ctx context.Context, in *MintCertRequest, opts ...grpc.CallOption) (*MintCertResponse, error) +} + +type sessionIdentityClient struct { + cc grpc.ClientConnInterface +} + +func NewSessionIdentityClient(cc grpc.ClientConnInterface) SessionIdentityClient { + return &sessionIdentityClient{cc} +} + +func (c *sessionIdentityClient) MintJWT(ctx context.Context, in *MintJWTRequest, opts ...grpc.CallOption) (*MintJWTResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MintJWTResponse) + err := c.cc.Invoke(ctx, SessionIdentity_MintJWT_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionIdentityClient) MintCert(ctx context.Context, in *MintCertRequest, opts ...grpc.CallOption) (*MintCertResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MintCertResponse) + err := c.cc.Invoke(ctx, SessionIdentity_MintCert_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SessionIdentityServer is the server API for SessionIdentity service. +// All implementations must embed UnimplementedSessionIdentityServer +// for forward compatibility. +// +// SessionIdentity allows substrate workloads to exchange their +// infrastructure-level credentials (k8s service account token, etc.) for a +// substrate session-level credential. A given substrate session might migrate +// between many different physical workers over the course of its lifecycle, +// whereas the session credential's identity will be stable for the life of the +// session. +// +// This service requires authentication. You can authenticate with a Kubernetes +// service account token in an `Authorization: Bearer` header, or you can +// authenticate with a Kubernetes service account certificate as an mTLS +// certificate. (Kubernetes service account certificates do not currently exist +// upstream, but we will provide a polyfill based on Pod Certificates). +// +// The broker will check that the service credentials you authenticated with +// belong to a Pod that is currently mapped to the requested session in the +// session database. +type SessionIdentityServer interface { + // Request a Session Identity JWT. + // + // To call this RPC, you must be authenticated as the Kubernetes Pod that is + // currently running the requested session. + MintJWT(context.Context, *MintJWTRequest) (*MintJWTResponse, error) + // Request a Session Identity Certificate. To call this RPC, you must have + // authenticated with a client certificate, not a bearer token. + MintCert(context.Context, *MintCertRequest) (*MintCertResponse, error) + mustEmbedUnimplementedSessionIdentityServer() +} + +// UnimplementedSessionIdentityServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedSessionIdentityServer struct{} + +func (UnimplementedSessionIdentityServer) MintJWT(context.Context, *MintJWTRequest) (*MintJWTResponse, error) { + return nil, status.Error(codes.Unimplemented, "method MintJWT not implemented") +} +func (UnimplementedSessionIdentityServer) MintCert(context.Context, *MintCertRequest) (*MintCertResponse, error) { + return nil, status.Error(codes.Unimplemented, "method MintCert not implemented") +} +func (UnimplementedSessionIdentityServer) mustEmbedUnimplementedSessionIdentityServer() {} +func (UnimplementedSessionIdentityServer) testEmbeddedByValue() {} + +// UnsafeSessionIdentityServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SessionIdentityServer will +// result in compilation errors. +type UnsafeSessionIdentityServer interface { + mustEmbedUnimplementedSessionIdentityServer() +} + +func RegisterSessionIdentityServer(s grpc.ServiceRegistrar, srv SessionIdentityServer) { + // If the following call panics, it indicates UnimplementedSessionIdentityServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&SessionIdentity_ServiceDesc, srv) +} + +func _SessionIdentity_MintJWT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MintJWTRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionIdentityServer).MintJWT(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SessionIdentity_MintJWT_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionIdentityServer).MintJWT(ctx, req.(*MintJWTRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionIdentity_MintCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MintCertRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionIdentityServer).MintCert(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SessionIdentity_MintCert_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionIdentityServer).MintCert(ctx, req.(*MintCertRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// SessionIdentity_ServiceDesc is the grpc.ServiceDesc for SessionIdentity service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SessionIdentity_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ateapi.SessionIdentity", + HandlerType: (*SessionIdentityServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "MintJWT", + Handler: _SessionIdentity_MintJWT_Handler, + }, + { + MethodName: "MintCert", + Handler: _SessionIdentity_MintCert_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ateapi.proto", +} diff --git a/proto/ateapipb/gen.go b/proto/ateapipb/gen.go new file mode 100644 index 000000000..8fa54cdfb --- /dev/null +++ b/proto/ateapipb/gen.go @@ -0,0 +1,17 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ateapipb + +//go:generate bash -c "../../hack/protoc.sh --plugin=protoc-gen-go=$(bash ../../hack/run-tool.sh --print-bin-path protoc-gen-go) --plugin=protoc-gen-go-grpc=$(bash ../../hack/run-tool.sh --print-bin-path protoc-gen-go-grpc) --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. ateapi.proto" diff --git a/proto/ateletpb/atelet.pb.go b/proto/ateletpb/atelet.pb.go new file mode 100644 index 000000000..597a33987 --- /dev/null +++ b/proto/ateletpb/atelet.pb.go @@ -0,0 +1,969 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11-devel +// protoc v4.25.3 +// source: atelet.proto + +package ateletpb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RunRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + TargetAteomNamespace string `protobuf:"bytes,1,opt,name=target_ateom_namespace,json=targetAteomNamespace,proto3" json:"target_ateom_namespace,omitempty"` + TargetAteomName string `protobuf:"bytes,2,opt,name=target_ateom_name,json=targetAteomName,proto3" json:"target_ateom_name,omitempty"` + ActorTemplateNamespace string `protobuf:"bytes,3,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,4,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + ActorId string `protobuf:"bytes,5,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + Runsc *RunscConfig `protobuf:"bytes,8,opt,name=runsc,proto3" json:"runsc,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,7,opt,name=spec,proto3" json:"spec,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunRequest) Reset() { + *x = RunRequest{} + mi := &file_atelet_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunRequest) ProtoMessage() {} + +func (x *RunRequest) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunRequest.ProtoReflect.Descriptor instead. +func (*RunRequest) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{0} +} + +func (x *RunRequest) GetTargetAteomNamespace() string { + if x != nil { + return x.TargetAteomNamespace + } + return "" +} + +func (x *RunRequest) GetTargetAteomName() string { + if x != nil { + return x.TargetAteomName + } + return "" +} + +func (x *RunRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *RunRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *RunRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *RunRequest) GetRunsc() *RunscConfig { + if x != nil { + return x.Runsc + } + return nil +} + +func (x *RunRequest) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +type GCPAuthenticationConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + Use bool `protobuf:"varint,1,opt,name=use,proto3" json:"use,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GCPAuthenticationConfig) Reset() { + *x = GCPAuthenticationConfig{} + mi := &file_atelet_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GCPAuthenticationConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GCPAuthenticationConfig) ProtoMessage() {} + +func (x *GCPAuthenticationConfig) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GCPAuthenticationConfig.ProtoReflect.Descriptor instead. +func (*GCPAuthenticationConfig) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{1} +} + +func (x *GCPAuthenticationConfig) GetUse() bool { + if x != nil { + return x.Use + } + return false +} + +type AuthenticationConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + Gcp *GCPAuthenticationConfig `protobuf:"bytes,1,opt,name=gcp,proto3" json:"gcp,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AuthenticationConfig) Reset() { + *x = AuthenticationConfig{} + mi := &file_atelet_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AuthenticationConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthenticationConfig) ProtoMessage() {} + +func (x *AuthenticationConfig) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AuthenticationConfig.ProtoReflect.Descriptor instead. +func (*AuthenticationConfig) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{2} +} + +func (x *AuthenticationConfig) GetGcp() *GCPAuthenticationConfig { + if x != nil { + return x.Gcp + } + return nil +} + +type RunscPlatformConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Check the downloaded binary against this hash. Also used for naming the + // downloaded file to prevent collisions. + Sha256Hash string `protobuf:"bytes,1,opt,name=sha256_hash,json=sha256Hash,proto3" json:"sha256_hash,omitempty"` + // gs:// URL to download the runsc binary. + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunscPlatformConfig) Reset() { + *x = RunscPlatformConfig{} + mi := &file_atelet_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunscPlatformConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunscPlatformConfig) ProtoMessage() {} + +func (x *RunscPlatformConfig) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunscPlatformConfig.ProtoReflect.Descriptor instead. +func (*RunscPlatformConfig) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{3} +} + +func (x *RunscPlatformConfig) GetSha256Hash() string { + if x != nil { + return x.Sha256Hash + } + return "" +} + +func (x *RunscPlatformConfig) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type RunscConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + Amd64 *RunscPlatformConfig `protobuf:"bytes,1,opt,name=amd64,proto3" json:"amd64,omitempty"` + Arm64 *RunscPlatformConfig `protobuf:"bytes,2,opt,name=arm64,proto3" json:"arm64,omitempty"` + // How should atelet authenticate to fetch the runsc binary? + Authentication *AuthenticationConfig `protobuf:"bytes,3,opt,name=authentication,proto3" json:"authentication,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunscConfig) Reset() { + *x = RunscConfig{} + mi := &file_atelet_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunscConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunscConfig) ProtoMessage() {} + +func (x *RunscConfig) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunscConfig.ProtoReflect.Descriptor instead. +func (*RunscConfig) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{4} +} + +func (x *RunscConfig) GetAmd64() *RunscPlatformConfig { + if x != nil { + return x.Amd64 + } + return nil +} + +func (x *RunscConfig) GetArm64() *RunscPlatformConfig { + if x != nil { + return x.Arm64 + } + return nil +} + +func (x *RunscConfig) GetAuthentication() *AuthenticationConfig { + if x != nil { + return x.Authentication + } + return nil +} + +// WorkloadSpec parallels Pod, but with far fewer configurable fields. +type WorkloadSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Containers []*Container `protobuf:"bytes,1,rep,name=containers,proto3" json:"containers,omitempty"` + PauseImage string `protobuf:"bytes,2,opt,name=pause_image,json=pauseImage,proto3" json:"pause_image,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadSpec) Reset() { + *x = WorkloadSpec{} + mi := &file_atelet_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadSpec) ProtoMessage() {} + +func (x *WorkloadSpec) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadSpec.ProtoReflect.Descriptor instead. +func (*WorkloadSpec) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{5} +} + +func (x *WorkloadSpec) GetContainers() []*Container { + if x != nil { + return x.Containers + } + return nil +} + +func (x *WorkloadSpec) GetPauseImage() string { + if x != nil { + return x.PauseImage + } + return "" +} + +type Container struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Image string `protobuf:"bytes,2,opt,name=image,proto3" json:"image,omitempty"` + Command []string `protobuf:"bytes,3,rep,name=command,proto3" json:"command,omitempty"` + Env []*EnvEntry `protobuf:"bytes,4,rep,name=env,proto3" json:"env,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Container) Reset() { + *x = Container{} + mi := &file_atelet_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Container) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Container) ProtoMessage() {} + +func (x *Container) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Container.ProtoReflect.Descriptor instead. +func (*Container) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{6} +} + +func (x *Container) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Container) GetImage() string { + if x != nil { + return x.Image + } + return "" +} + +func (x *Container) GetCommand() []string { + if x != nil { + return x.Command + } + return nil +} + +func (x *Container) GetEnv() []*EnvEntry { + if x != nil { + return x.Env + } + return nil +} + +type EnvEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EnvEntry) Reset() { + *x = EnvEntry{} + mi := &file_atelet_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EnvEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnvEntry) ProtoMessage() {} + +func (x *EnvEntry) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnvEntry.ProtoReflect.Descriptor instead. +func (*EnvEntry) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{7} +} + +func (x *EnvEntry) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *EnvEntry) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type RunResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunResponse) Reset() { + *x = RunResponse{} + mi := &file_atelet_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunResponse) ProtoMessage() {} + +func (x *RunResponse) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunResponse.ProtoReflect.Descriptor instead. +func (*RunResponse) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{8} +} + +type CheckpointRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + TargetAteomNamespace string `protobuf:"bytes,1,opt,name=target_ateom_namespace,json=targetAteomNamespace,proto3" json:"target_ateom_namespace,omitempty"` + TargetAteomName string `protobuf:"bytes,2,opt,name=target_ateom_name,json=targetAteomName,proto3" json:"target_ateom_name,omitempty"` + ActorTemplateNamespace string `protobuf:"bytes,3,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,4,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + ActorId string `protobuf:"bytes,5,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + Runsc *RunscConfig `protobuf:"bytes,6,opt,name=runsc,proto3" json:"runsc,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,7,opt,name=spec,proto3" json:"spec,omitempty"` + // An object storage URI prefix below which the checkpoint data will be + // stored. + // + // The structure of the checkpoint should generally be treated as opaque. For + // gVisor, the checkpoint consists of a checkpoint.img file that contains the + // memory, sentry state, and filesystem deltas. ateom will write additional + // files to store the WorkloadSpec, which must be reassembled before gVisor + // can restore a checkpoint. + // + // For example: "gs://bucket/actors/1234/snapshots/5678/" + SnapshotUriPrefix string `protobuf:"bytes,8,opt,name=snapshot_uri_prefix,json=snapshotUriPrefix,proto3" json:"snapshot_uri_prefix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckpointRequest) Reset() { + *x = CheckpointRequest{} + mi := &file_atelet_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckpointRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckpointRequest) ProtoMessage() {} + +func (x *CheckpointRequest) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckpointRequest.ProtoReflect.Descriptor instead. +func (*CheckpointRequest) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{9} +} + +func (x *CheckpointRequest) GetTargetAteomNamespace() string { + if x != nil { + return x.TargetAteomNamespace + } + return "" +} + +func (x *CheckpointRequest) GetTargetAteomName() string { + if x != nil { + return x.TargetAteomName + } + return "" +} + +func (x *CheckpointRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *CheckpointRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *CheckpointRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *CheckpointRequest) GetRunsc() *RunscConfig { + if x != nil { + return x.Runsc + } + return nil +} + +func (x *CheckpointRequest) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *CheckpointRequest) GetSnapshotUriPrefix() string { + if x != nil { + return x.SnapshotUriPrefix + } + return "" +} + +type CheckpointResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckpointResponse) Reset() { + *x = CheckpointResponse{} + mi := &file_atelet_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckpointResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckpointResponse) ProtoMessage() {} + +func (x *CheckpointResponse) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckpointResponse.ProtoReflect.Descriptor instead. +func (*CheckpointResponse) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{10} +} + +type RestoreRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + TargetAteomNamespace string `protobuf:"bytes,1,opt,name=target_ateom_namespace,json=targetAteomNamespace,proto3" json:"target_ateom_namespace,omitempty"` + TargetAteomName string `protobuf:"bytes,2,opt,name=target_ateom_name,json=targetAteomName,proto3" json:"target_ateom_name,omitempty"` + ActorTemplateNamespace string `protobuf:"bytes,3,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,4,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + ActorId string `protobuf:"bytes,5,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + Runsc *RunscConfig `protobuf:"bytes,6,opt,name=runsc,proto3" json:"runsc,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,7,opt,name=spec,proto3" json:"spec,omitempty"` + // The object storage URI prefix of the snapshot to restore. + SnapshotUriPrefix string `protobuf:"bytes,8,opt,name=snapshot_uri_prefix,json=snapshotUriPrefix,proto3" json:"snapshot_uri_prefix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestoreRequest) Reset() { + *x = RestoreRequest{} + mi := &file_atelet_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestoreRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestoreRequest) ProtoMessage() {} + +func (x *RestoreRequest) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestoreRequest.ProtoReflect.Descriptor instead. +func (*RestoreRequest) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{11} +} + +func (x *RestoreRequest) GetTargetAteomNamespace() string { + if x != nil { + return x.TargetAteomNamespace + } + return "" +} + +func (x *RestoreRequest) GetTargetAteomName() string { + if x != nil { + return x.TargetAteomName + } + return "" +} + +func (x *RestoreRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *RestoreRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *RestoreRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *RestoreRequest) GetRunsc() *RunscConfig { + if x != nil { + return x.Runsc + } + return nil +} + +func (x *RestoreRequest) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *RestoreRequest) GetSnapshotUriPrefix() string { + if x != nil { + return x.SnapshotUriPrefix + } + return "" +} + +type RestoreResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestoreResponse) Reset() { + *x = RestoreResponse{} + mi := &file_atelet_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestoreResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestoreResponse) ProtoMessage() {} + +func (x *RestoreResponse) ProtoReflect() protoreflect.Message { + mi := &file_atelet_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestoreResponse.ProtoReflect.Descriptor instead. +func (*RestoreResponse) Descriptor() ([]byte, []int) { + return file_atelet_proto_rawDescGZIP(), []int{12} +} + +var File_atelet_proto protoreflect.FileDescriptor + +const file_atelet_proto_rawDesc = "" + + "\n" + + "\fatelet.proto\x12\x06atelet\"\xc8\x02\n" + + "\n" + + "RunRequest\x124\n" + + "\x16target_ateom_namespace\x18\x01 \x01(\tR\x14targetAteomNamespace\x12*\n" + + "\x11target_ateom_name\x18\x02 \x01(\tR\x0ftargetAteomName\x128\n" + + "\x18actor_template_namespace\x18\x03 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x04 \x01(\tR\x11actorTemplateName\x12\x19\n" + + "\bactor_id\x18\x05 \x01(\tR\aactorId\x12)\n" + + "\x05runsc\x18\b \x01(\v2\x13.atelet.RunscConfigR\x05runsc\x12(\n" + + "\x04spec\x18\a \x01(\v2\x14.atelet.WorkloadSpecR\x04spec\"+\n" + + "\x17GCPAuthenticationConfig\x12\x10\n" + + "\x03use\x18\x01 \x01(\bR\x03use\"I\n" + + "\x14AuthenticationConfig\x121\n" + + "\x03gcp\x18\x01 \x01(\v2\x1f.atelet.GCPAuthenticationConfigR\x03gcp\"H\n" + + "\x13RunscPlatformConfig\x12\x1f\n" + + "\vsha256_hash\x18\x01 \x01(\tR\n" + + "sha256Hash\x12\x10\n" + + "\x03url\x18\x02 \x01(\tR\x03url\"\xb9\x01\n" + + "\vRunscConfig\x121\n" + + "\x05amd64\x18\x01 \x01(\v2\x1b.atelet.RunscPlatformConfigR\x05amd64\x121\n" + + "\x05arm64\x18\x02 \x01(\v2\x1b.atelet.RunscPlatformConfigR\x05arm64\x12D\n" + + "\x0eauthentication\x18\x03 \x01(\v2\x1c.atelet.AuthenticationConfigR\x0eauthentication\"b\n" + + "\fWorkloadSpec\x121\n" + + "\n" + + "containers\x18\x01 \x03(\v2\x11.atelet.ContainerR\n" + + "containers\x12\x1f\n" + + "\vpause_image\x18\x02 \x01(\tR\n" + + "pauseImage\"s\n" + + "\tContainer\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + + "\x05image\x18\x02 \x01(\tR\x05image\x12\x18\n" + + "\acommand\x18\x03 \x03(\tR\acommand\x12\"\n" + + "\x03env\x18\x04 \x03(\v2\x10.atelet.EnvEntryR\x03env\"4\n" + + "\bEnvEntry\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value\"\r\n" + + "\vRunResponse\"\xff\x02\n" + + "\x11CheckpointRequest\x124\n" + + "\x16target_ateom_namespace\x18\x01 \x01(\tR\x14targetAteomNamespace\x12*\n" + + "\x11target_ateom_name\x18\x02 \x01(\tR\x0ftargetAteomName\x128\n" + + "\x18actor_template_namespace\x18\x03 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x04 \x01(\tR\x11actorTemplateName\x12\x19\n" + + "\bactor_id\x18\x05 \x01(\tR\aactorId\x12)\n" + + "\x05runsc\x18\x06 \x01(\v2\x13.atelet.RunscConfigR\x05runsc\x12(\n" + + "\x04spec\x18\a \x01(\v2\x14.atelet.WorkloadSpecR\x04spec\x12.\n" + + "\x13snapshot_uri_prefix\x18\b \x01(\tR\x11snapshotUriPrefix\"\x14\n" + + "\x12CheckpointResponse\"\xfc\x02\n" + + "\x0eRestoreRequest\x124\n" + + "\x16target_ateom_namespace\x18\x01 \x01(\tR\x14targetAteomNamespace\x12*\n" + + "\x11target_ateom_name\x18\x02 \x01(\tR\x0ftargetAteomName\x128\n" + + "\x18actor_template_namespace\x18\x03 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x04 \x01(\tR\x11actorTemplateName\x12\x19\n" + + "\bactor_id\x18\x05 \x01(\tR\aactorId\x12)\n" + + "\x05runsc\x18\x06 \x01(\v2\x13.atelet.RunscConfigR\x05runsc\x12(\n" + + "\x04spec\x18\a \x01(\v2\x14.atelet.WorkloadSpecR\x04spec\x12.\n" + + "\x13snapshot_uri_prefix\x18\b \x01(\tR\x11snapshotUriPrefix\"\x11\n" + + "\x0fRestoreResponse2\xc4\x01\n" + + "\vAteomHerder\x120\n" + + "\x03Run\x12\x12.atelet.RunRequest\x1a\x13.atelet.RunResponse\"\x00\x12E\n" + + "\n" + + "Checkpoint\x12\x19.atelet.CheckpointRequest\x1a\x1a.atelet.CheckpointResponse\"\x00\x12<\n" + + "\aRestore\x12\x16.atelet.RestoreRequest\x1a\x17.atelet.RestoreResponse\"\x00B5Z3github.com/agent-substrate/substrate/proto/ateletpbb\x06proto3" + +var ( + file_atelet_proto_rawDescOnce sync.Once + file_atelet_proto_rawDescData []byte +) + +func file_atelet_proto_rawDescGZIP() []byte { + file_atelet_proto_rawDescOnce.Do(func() { + file_atelet_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_atelet_proto_rawDesc), len(file_atelet_proto_rawDesc))) + }) + return file_atelet_proto_rawDescData +} + +var file_atelet_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_atelet_proto_goTypes = []any{ + (*RunRequest)(nil), // 0: atelet.RunRequest + (*GCPAuthenticationConfig)(nil), // 1: atelet.GCPAuthenticationConfig + (*AuthenticationConfig)(nil), // 2: atelet.AuthenticationConfig + (*RunscPlatformConfig)(nil), // 3: atelet.RunscPlatformConfig + (*RunscConfig)(nil), // 4: atelet.RunscConfig + (*WorkloadSpec)(nil), // 5: atelet.WorkloadSpec + (*Container)(nil), // 6: atelet.Container + (*EnvEntry)(nil), // 7: atelet.EnvEntry + (*RunResponse)(nil), // 8: atelet.RunResponse + (*CheckpointRequest)(nil), // 9: atelet.CheckpointRequest + (*CheckpointResponse)(nil), // 10: atelet.CheckpointResponse + (*RestoreRequest)(nil), // 11: atelet.RestoreRequest + (*RestoreResponse)(nil), // 12: atelet.RestoreResponse +} +var file_atelet_proto_depIdxs = []int32{ + 4, // 0: atelet.RunRequest.runsc:type_name -> atelet.RunscConfig + 5, // 1: atelet.RunRequest.spec:type_name -> atelet.WorkloadSpec + 1, // 2: atelet.AuthenticationConfig.gcp:type_name -> atelet.GCPAuthenticationConfig + 3, // 3: atelet.RunscConfig.amd64:type_name -> atelet.RunscPlatformConfig + 3, // 4: atelet.RunscConfig.arm64:type_name -> atelet.RunscPlatformConfig + 2, // 5: atelet.RunscConfig.authentication:type_name -> atelet.AuthenticationConfig + 6, // 6: atelet.WorkloadSpec.containers:type_name -> atelet.Container + 7, // 7: atelet.Container.env:type_name -> atelet.EnvEntry + 4, // 8: atelet.CheckpointRequest.runsc:type_name -> atelet.RunscConfig + 5, // 9: atelet.CheckpointRequest.spec:type_name -> atelet.WorkloadSpec + 4, // 10: atelet.RestoreRequest.runsc:type_name -> atelet.RunscConfig + 5, // 11: atelet.RestoreRequest.spec:type_name -> atelet.WorkloadSpec + 0, // 12: atelet.AteomHerder.Run:input_type -> atelet.RunRequest + 9, // 13: atelet.AteomHerder.Checkpoint:input_type -> atelet.CheckpointRequest + 11, // 14: atelet.AteomHerder.Restore:input_type -> atelet.RestoreRequest + 8, // 15: atelet.AteomHerder.Run:output_type -> atelet.RunResponse + 10, // 16: atelet.AteomHerder.Checkpoint:output_type -> atelet.CheckpointResponse + 12, // 17: atelet.AteomHerder.Restore:output_type -> atelet.RestoreResponse + 15, // [15:18] is the sub-list for method output_type + 12, // [12:15] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name +} + +func init() { file_atelet_proto_init() } +func file_atelet_proto_init() { + if File_atelet_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_atelet_proto_rawDesc), len(file_atelet_proto_rawDesc)), + NumEnums: 0, + NumMessages: 13, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_atelet_proto_goTypes, + DependencyIndexes: file_atelet_proto_depIdxs, + MessageInfos: file_atelet_proto_msgTypes, + }.Build() + File_atelet_proto = out.File + file_atelet_proto_goTypes = nil + file_atelet_proto_depIdxs = nil +} diff --git a/proto/ateletpb/atelet.proto b/proto/ateletpb/atelet.proto new file mode 100644 index 000000000..c879af6bb --- /dev/null +++ b/proto/ateletpb/atelet.proto @@ -0,0 +1,141 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package atelet; + +option go_package = "github.com/agent-substrate/substrate/proto/ateletpb"; + +service AteomHerder { + // Run tells atelet to create a new containerized workload from scratch on an + // ateom. + rpc Run(RunRequest) returns (RunResponse) {} + + // Checkpoint tells atelet to save the current state of the workload on an + // ateom to object storage, and then completely the ateom to a blank state + // (back to "available" state.) + rpc Checkpoint(CheckpointRequest) returns (CheckpointResponse) {} + + // Restore restores a workload from checkpoint onto an ateom. + rpc Restore(RestoreRequest) returns (RestoreResponse) {} +} + +message RunRequest { + string target_ateom_namespace = 1; + string target_ateom_name = 2; + + string actor_template_namespace = 3; + string actor_template_name = 4; + string actor_id = 5; + + RunscConfig runsc = 8; + + WorkloadSpec spec = 7; +} + +message GCPAuthenticationConfig { + bool use = 1; +} + +message AuthenticationConfig { + GCPAuthenticationConfig gcp = 1; +} + +message RunscPlatformConfig { + // Check the downloaded binary against this hash. Also used for naming the + // downloaded file to prevent collisions. + string sha256_hash = 1; + + // gs:// URL to download the runsc binary. + string url = 2; +} + +message RunscConfig { + RunscPlatformConfig amd64 = 1; + RunscPlatformConfig arm64 = 2; + + // How should atelet authenticate to fetch the runsc binary? + AuthenticationConfig authentication = 3; +} + +// WorkloadSpec parallels Pod, but with far fewer configurable fields. +message WorkloadSpec { + repeated Container containers = 1; + string pause_image = 2; +} + +message Container { + string name = 1; + string image = 2; + repeated string command = 3; + repeated EnvEntry env = 4; +} + +message EnvEntry { + string name = 1; + string value = 2; +} + +message RunResponse { +} + +message CheckpointRequest { + string target_ateom_namespace = 1; + string target_ateom_name = 2; + + string actor_template_namespace = 3; + string actor_template_name = 4; + string actor_id = 5; + + RunscConfig runsc = 6; + + WorkloadSpec spec = 7; + + // An object storage URI prefix below which the checkpoint data will be + // stored. + // + // The structure of the checkpoint should generally be treated as opaque. For + // gVisor, the checkpoint consists of a checkpoint.img file that contains the + // memory, sentry state, and filesystem deltas. ateom will write additional + // files to store the WorkloadSpec, which must be reassembled before gVisor + // can restore a checkpoint. + // + // For example: "gs://bucket/actors/1234/snapshots/5678/" + string snapshot_uri_prefix = 8; +} + +message CheckpointResponse { + +} + +message RestoreRequest { + string target_ateom_namespace = 1; + string target_ateom_name = 2; + + string actor_template_namespace = 3; + string actor_template_name = 4; + string actor_id = 5; + + RunscConfig runsc = 6; + + WorkloadSpec spec = 7; + + // The object storage URI prefix of the snapshot to restore. + string snapshot_uri_prefix = 8; +} + +message RestoreResponse { + +} diff --git a/proto/ateletpb/atelet_grpc.pb.go b/proto/ateletpb/atelet_grpc.pb.go new file mode 100644 index 000000000..dabd3c207 --- /dev/null +++ b/proto/ateletpb/atelet_grpc.pb.go @@ -0,0 +1,223 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v4.25.3 +// source: atelet.proto + +package ateletpb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + AteomHerder_Run_FullMethodName = "/atelet.AteomHerder/Run" + AteomHerder_Checkpoint_FullMethodName = "/atelet.AteomHerder/Checkpoint" + AteomHerder_Restore_FullMethodName = "/atelet.AteomHerder/Restore" +) + +// AteomHerderClient is the client API for AteomHerder service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AteomHerderClient interface { + // Run tells atelet to create a new containerized workload from scratch on an + // ateom. + Run(ctx context.Context, in *RunRequest, opts ...grpc.CallOption) (*RunResponse, error) + // Checkpoint tells atelet to save the current state of the workload on an + // ateom to object storage, and then completely the ateom to a blank state + // (back to "available" state.) + Checkpoint(ctx context.Context, in *CheckpointRequest, opts ...grpc.CallOption) (*CheckpointResponse, error) + // Restore restores a workload from checkpoint onto an ateom. + Restore(ctx context.Context, in *RestoreRequest, opts ...grpc.CallOption) (*RestoreResponse, error) +} + +type ateomHerderClient struct { + cc grpc.ClientConnInterface +} + +func NewAteomHerderClient(cc grpc.ClientConnInterface) AteomHerderClient { + return &ateomHerderClient{cc} +} + +func (c *ateomHerderClient) Run(ctx context.Context, in *RunRequest, opts ...grpc.CallOption) (*RunResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RunResponse) + err := c.cc.Invoke(ctx, AteomHerder_Run_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ateomHerderClient) Checkpoint(ctx context.Context, in *CheckpointRequest, opts ...grpc.CallOption) (*CheckpointResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CheckpointResponse) + err := c.cc.Invoke(ctx, AteomHerder_Checkpoint_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ateomHerderClient) Restore(ctx context.Context, in *RestoreRequest, opts ...grpc.CallOption) (*RestoreResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RestoreResponse) + err := c.cc.Invoke(ctx, AteomHerder_Restore_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AteomHerderServer is the server API for AteomHerder service. +// All implementations must embed UnimplementedAteomHerderServer +// for forward compatibility. +type AteomHerderServer interface { + // Run tells atelet to create a new containerized workload from scratch on an + // ateom. + Run(context.Context, *RunRequest) (*RunResponse, error) + // Checkpoint tells atelet to save the current state of the workload on an + // ateom to object storage, and then completely the ateom to a blank state + // (back to "available" state.) + Checkpoint(context.Context, *CheckpointRequest) (*CheckpointResponse, error) + // Restore restores a workload from checkpoint onto an ateom. + Restore(context.Context, *RestoreRequest) (*RestoreResponse, error) + mustEmbedUnimplementedAteomHerderServer() +} + +// UnimplementedAteomHerderServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAteomHerderServer struct{} + +func (UnimplementedAteomHerderServer) Run(context.Context, *RunRequest) (*RunResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Run not implemented") +} +func (UnimplementedAteomHerderServer) Checkpoint(context.Context, *CheckpointRequest) (*CheckpointResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Checkpoint not implemented") +} +func (UnimplementedAteomHerderServer) Restore(context.Context, *RestoreRequest) (*RestoreResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Restore not implemented") +} +func (UnimplementedAteomHerderServer) mustEmbedUnimplementedAteomHerderServer() {} +func (UnimplementedAteomHerderServer) testEmbeddedByValue() {} + +// UnsafeAteomHerderServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AteomHerderServer will +// result in compilation errors. +type UnsafeAteomHerderServer interface { + mustEmbedUnimplementedAteomHerderServer() +} + +func RegisterAteomHerderServer(s grpc.ServiceRegistrar, srv AteomHerderServer) { + // If the following call panics, it indicates UnimplementedAteomHerderServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AteomHerder_ServiceDesc, srv) +} + +func _AteomHerder_Run_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RunRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AteomHerderServer).Run(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AteomHerder_Run_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AteomHerderServer).Run(ctx, req.(*RunRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AteomHerder_Checkpoint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckpointRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AteomHerderServer).Checkpoint(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AteomHerder_Checkpoint_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AteomHerderServer).Checkpoint(ctx, req.(*CheckpointRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AteomHerder_Restore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RestoreRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AteomHerderServer).Restore(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AteomHerder_Restore_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AteomHerderServer).Restore(ctx, req.(*RestoreRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AteomHerder_ServiceDesc is the grpc.ServiceDesc for AteomHerder service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AteomHerder_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "atelet.AteomHerder", + HandlerType: (*AteomHerderServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Run", + Handler: _AteomHerder_Run_Handler, + }, + { + MethodName: "Checkpoint", + Handler: _AteomHerder_Checkpoint_Handler, + }, + { + MethodName: "Restore", + Handler: _AteomHerder_Restore_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "atelet.proto", +} diff --git a/proto/ateletpb/gen.go b/proto/ateletpb/gen.go new file mode 100644 index 000000000..6334003e6 --- /dev/null +++ b/proto/ateletpb/gen.go @@ -0,0 +1,17 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ateletpb + +//go:generate bash -c "../../hack/protoc.sh --plugin=protoc-gen-go=$(bash ../../hack/run-tool.sh --print-bin-path protoc-gen-go) --plugin=protoc-gen-go-grpc=$(bash ../../hack/run-tool.sh --print-bin-path protoc-gen-go-grpc) --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. atelet.proto" diff --git a/proto/ateompb/ateom.pb.go b/proto/ateompb/ateom.pb.go new file mode 100644 index 000000000..df6451782 --- /dev/null +++ b/proto/ateompb/ateom.pb.go @@ -0,0 +1,593 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11-devel +// protoc v4.25.3 +// source: ateom.proto + +package ateompb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RunWorkloadRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorTemplateNamespace string `protobuf:"bytes,1,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,2,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + ActorId string `protobuf:"bytes,3,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + RunscPath string `protobuf:"bytes,4,opt,name=runsc_path,json=runscPath,proto3" json:"runsc_path,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunWorkloadRequest) Reset() { + *x = RunWorkloadRequest{} + mi := &file_ateom_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunWorkloadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunWorkloadRequest) ProtoMessage() {} + +func (x *RunWorkloadRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunWorkloadRequest.ProtoReflect.Descriptor instead. +func (*RunWorkloadRequest) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{0} +} + +func (x *RunWorkloadRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *RunWorkloadRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *RunWorkloadRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *RunWorkloadRequest) GetRunscPath() string { + if x != nil { + return x.RunscPath + } + return "" +} + +func (x *RunWorkloadRequest) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +// WorkloadSpec parallels Pod, but with far fewer configurable fields. +type WorkloadSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Containers []*Container `protobuf:"bytes,1,rep,name=containers,proto3" json:"containers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadSpec) Reset() { + *x = WorkloadSpec{} + mi := &file_ateom_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadSpec) ProtoMessage() {} + +func (x *WorkloadSpec) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadSpec.ProtoReflect.Descriptor instead. +func (*WorkloadSpec) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{1} +} + +func (x *WorkloadSpec) GetContainers() []*Container { + if x != nil { + return x.Containers + } + return nil +} + +type Container struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Container) Reset() { + *x = Container{} + mi := &file_ateom_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Container) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Container) ProtoMessage() {} + +func (x *Container) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Container.ProtoReflect.Descriptor instead. +func (*Container) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{2} +} + +func (x *Container) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type RunWorkloadResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RunWorkloadResponse) Reset() { + *x = RunWorkloadResponse{} + mi := &file_ateom_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RunWorkloadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RunWorkloadResponse) ProtoMessage() {} + +func (x *RunWorkloadResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RunWorkloadResponse.ProtoReflect.Descriptor instead. +func (*RunWorkloadResponse) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{3} +} + +type CheckpointWorkloadRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorTemplateNamespace string `protobuf:"bytes,1,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,2,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + ActorId string `protobuf:"bytes,3,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + RunscPath string `protobuf:"bytes,4,opt,name=runsc_path,json=runscPath,proto3" json:"runsc_path,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` + // An object storage URI prefix below which the checkpoint data will be + // stored. + // + // The structure of the checkpoint should generally be treated as opaque. For + // gVisor, the checkpoint consists of a checkpoint.img file that contains the + // memory, sentry state, and filesystem deltas. + // + // For example: "gs://bucket/actors/1234/snapshots/5678/" + SnapshotUriPrefix string `protobuf:"bytes,6,opt,name=snapshot_uri_prefix,json=snapshotUriPrefix,proto3" json:"snapshot_uri_prefix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckpointWorkloadRequest) Reset() { + *x = CheckpointWorkloadRequest{} + mi := &file_ateom_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckpointWorkloadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckpointWorkloadRequest) ProtoMessage() {} + +func (x *CheckpointWorkloadRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckpointWorkloadRequest.ProtoReflect.Descriptor instead. +func (*CheckpointWorkloadRequest) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{4} +} + +func (x *CheckpointWorkloadRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *CheckpointWorkloadRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *CheckpointWorkloadRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *CheckpointWorkloadRequest) GetRunscPath() string { + if x != nil { + return x.RunscPath + } + return "" +} + +func (x *CheckpointWorkloadRequest) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *CheckpointWorkloadRequest) GetSnapshotUriPrefix() string { + if x != nil { + return x.SnapshotUriPrefix + } + return "" +} + +type CheckpointWorkloadResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckpointWorkloadResponse) Reset() { + *x = CheckpointWorkloadResponse{} + mi := &file_ateom_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckpointWorkloadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckpointWorkloadResponse) ProtoMessage() {} + +func (x *CheckpointWorkloadResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckpointWorkloadResponse.ProtoReflect.Descriptor instead. +func (*CheckpointWorkloadResponse) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{5} +} + +type RestoreWorkloadRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ActorTemplateNamespace string `protobuf:"bytes,1,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,2,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + ActorId string `protobuf:"bytes,3,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` + RunscPath string `protobuf:"bytes,4,opt,name=runsc_path,json=runscPath,proto3" json:"runsc_path,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` + // The object storage URI prefix of the snapshot to restore. + SnapshotUriPrefix string `protobuf:"bytes,6,opt,name=snapshot_uri_prefix,json=snapshotUriPrefix,proto3" json:"snapshot_uri_prefix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestoreWorkloadRequest) Reset() { + *x = RestoreWorkloadRequest{} + mi := &file_ateom_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestoreWorkloadRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestoreWorkloadRequest) ProtoMessage() {} + +func (x *RestoreWorkloadRequest) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestoreWorkloadRequest.ProtoReflect.Descriptor instead. +func (*RestoreWorkloadRequest) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{6} +} + +func (x *RestoreWorkloadRequest) GetActorTemplateNamespace() string { + if x != nil { + return x.ActorTemplateNamespace + } + return "" +} + +func (x *RestoreWorkloadRequest) GetActorTemplateName() string { + if x != nil { + return x.ActorTemplateName + } + return "" +} + +func (x *RestoreWorkloadRequest) GetActorId() string { + if x != nil { + return x.ActorId + } + return "" +} + +func (x *RestoreWorkloadRequest) GetRunscPath() string { + if x != nil { + return x.RunscPath + } + return "" +} + +func (x *RestoreWorkloadRequest) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *RestoreWorkloadRequest) GetSnapshotUriPrefix() string { + if x != nil { + return x.SnapshotUriPrefix + } + return "" +} + +type RestoreWorkloadResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestoreWorkloadResponse) Reset() { + *x = RestoreWorkloadResponse{} + mi := &file_ateom_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestoreWorkloadResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestoreWorkloadResponse) ProtoMessage() {} + +func (x *RestoreWorkloadResponse) ProtoReflect() protoreflect.Message { + mi := &file_ateom_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestoreWorkloadResponse.ProtoReflect.Descriptor instead. +func (*RestoreWorkloadResponse) Descriptor() ([]byte, []int) { + return file_ateom_proto_rawDescGZIP(), []int{7} +} + +var File_ateom_proto protoreflect.FileDescriptor + +const file_ateom_proto_rawDesc = "" + + "\n" + + "\vateom.proto\x12\x05ateom\"\xe1\x01\n" + + "\x12RunWorkloadRequest\x128\n" + + "\x18actor_template_namespace\x18\x01 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x02 \x01(\tR\x11actorTemplateName\x12\x19\n" + + "\bactor_id\x18\x03 \x01(\tR\aactorId\x12\x1d\n" + + "\n" + + "runsc_path\x18\x04 \x01(\tR\trunscPath\x12'\n" + + "\x04spec\x18\x05 \x01(\v2\x13.ateom.WorkloadSpecR\x04spec\"@\n" + + "\fWorkloadSpec\x120\n" + + "\n" + + "containers\x18\x01 \x03(\v2\x10.ateom.ContainerR\n" + + "containers\"\x1f\n" + + "\tContainer\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"\x15\n" + + "\x13RunWorkloadResponse\"\x98\x02\n" + + "\x19CheckpointWorkloadRequest\x128\n" + + "\x18actor_template_namespace\x18\x01 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x02 \x01(\tR\x11actorTemplateName\x12\x19\n" + + "\bactor_id\x18\x03 \x01(\tR\aactorId\x12\x1d\n" + + "\n" + + "runsc_path\x18\x04 \x01(\tR\trunscPath\x12'\n" + + "\x04spec\x18\x05 \x01(\v2\x13.ateom.WorkloadSpecR\x04spec\x12.\n" + + "\x13snapshot_uri_prefix\x18\x06 \x01(\tR\x11snapshotUriPrefix\"\x1c\n" + + "\x1aCheckpointWorkloadResponse\"\x95\x02\n" + + "\x16RestoreWorkloadRequest\x128\n" + + "\x18actor_template_namespace\x18\x01 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x02 \x01(\tR\x11actorTemplateName\x12\x19\n" + + "\bactor_id\x18\x03 \x01(\tR\aactorId\x12\x1d\n" + + "\n" + + "runsc_path\x18\x04 \x01(\tR\trunscPath\x12'\n" + + "\x04spec\x18\x05 \x01(\v2\x13.ateom.WorkloadSpecR\x04spec\x12.\n" + + "\x13snapshot_uri_prefix\x18\x06 \x01(\tR\x11snapshotUriPrefix\"\x19\n" + + "\x17RestoreWorkloadResponse2\x80\x02\n" + + "\x05Ateom\x12F\n" + + "\vRunWorkload\x12\x19.ateom.RunWorkloadRequest\x1a\x1a.ateom.RunWorkloadResponse\"\x00\x12[\n" + + "\x12CheckpointWorkload\x12 .ateom.CheckpointWorkloadRequest\x1a!.ateom.CheckpointWorkloadResponse\"\x00\x12R\n" + + "\x0fRestoreWorkload\x12\x1d.ateom.RestoreWorkloadRequest\x1a\x1e.ateom.RestoreWorkloadResponse\"\x00B4Z2github.com/agent-substrate/substrate/proto/ateompbb\x06proto3" + +var ( + file_ateom_proto_rawDescOnce sync.Once + file_ateom_proto_rawDescData []byte +) + +func file_ateom_proto_rawDescGZIP() []byte { + file_ateom_proto_rawDescOnce.Do(func() { + file_ateom_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ateom_proto_rawDesc), len(file_ateom_proto_rawDesc))) + }) + return file_ateom_proto_rawDescData +} + +var file_ateom_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_ateom_proto_goTypes = []any{ + (*RunWorkloadRequest)(nil), // 0: ateom.RunWorkloadRequest + (*WorkloadSpec)(nil), // 1: ateom.WorkloadSpec + (*Container)(nil), // 2: ateom.Container + (*RunWorkloadResponse)(nil), // 3: ateom.RunWorkloadResponse + (*CheckpointWorkloadRequest)(nil), // 4: ateom.CheckpointWorkloadRequest + (*CheckpointWorkloadResponse)(nil), // 5: ateom.CheckpointWorkloadResponse + (*RestoreWorkloadRequest)(nil), // 6: ateom.RestoreWorkloadRequest + (*RestoreWorkloadResponse)(nil), // 7: ateom.RestoreWorkloadResponse +} +var file_ateom_proto_depIdxs = []int32{ + 1, // 0: ateom.RunWorkloadRequest.spec:type_name -> ateom.WorkloadSpec + 2, // 1: ateom.WorkloadSpec.containers:type_name -> ateom.Container + 1, // 2: ateom.CheckpointWorkloadRequest.spec:type_name -> ateom.WorkloadSpec + 1, // 3: ateom.RestoreWorkloadRequest.spec:type_name -> ateom.WorkloadSpec + 0, // 4: ateom.Ateom.RunWorkload:input_type -> ateom.RunWorkloadRequest + 4, // 5: ateom.Ateom.CheckpointWorkload:input_type -> ateom.CheckpointWorkloadRequest + 6, // 6: ateom.Ateom.RestoreWorkload:input_type -> ateom.RestoreWorkloadRequest + 3, // 7: ateom.Ateom.RunWorkload:output_type -> ateom.RunWorkloadResponse + 5, // 8: ateom.Ateom.CheckpointWorkload:output_type -> ateom.CheckpointWorkloadResponse + 7, // 9: ateom.Ateom.RestoreWorkload:output_type -> ateom.RestoreWorkloadResponse + 7, // [7:10] is the sub-list for method output_type + 4, // [4:7] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_ateom_proto_init() } +func file_ateom_proto_init() { + if File_ateom_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_ateom_proto_rawDesc), len(file_ateom_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_ateom_proto_goTypes, + DependencyIndexes: file_ateom_proto_depIdxs, + MessageInfos: file_ateom_proto_msgTypes, + }.Build() + File_ateom_proto = out.File + file_ateom_proto_goTypes = nil + file_ateom_proto_depIdxs = nil +} diff --git a/proto/ateompb/ateom.proto b/proto/ateompb/ateom.proto new file mode 100644 index 000000000..8b4578d15 --- /dev/null +++ b/proto/ateompb/ateom.proto @@ -0,0 +1,111 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package ateom; + +option go_package = "github.com/agent-substrate/substrate/proto/ateompb"; + +// Ateom is the interface to control a single gVisor (or, in the future microVM) +// guest inside a worker pod. +// +// Each ateom server has two main states, "available" and "executing". +// +// When the ateom is "available", the substrate control plane is free to either +// boot a new workload (using RunWorkload), or restore an existing workload from +// a checkpoint (using RestoreWorkload). These calls move the ateom into +// "executing" state. +// +// When the ateom is "executing", the substrate control plane can checkpoint the +// running workload (with CheckpointWorkload). This moves the ateom back to +// "free" state. +service Ateom { + // RunWorkload tells ateom to begin running a new workload (one or more + // containers, potentially with shared filesystems). + rpc RunWorkload(RunWorkloadRequest) returns (RunWorkloadResponse) {} + + // CheckpointWorkload tells ateom to save the current state of the running + // workload to object storage, and then completely reset itself to a blank + // state (back to "available" state.) + rpc CheckpointWorkload(CheckpointWorkloadRequest) returns (CheckpointWorkloadResponse) {} + + // RestoreWorkload restores a workload from checkpoint that was previously + // written by CheckpointWorkload. Ateom will handle downloading the correct + // gVisor / runsc version to match the checkpoint. + rpc RestoreWorkload(RestoreWorkloadRequest) returns (RestoreWorkloadResponse) {} +} + +message RunWorkloadRequest { + string actor_template_namespace = 1; + string actor_template_name = 2; + string actor_id = 3; + + string runsc_path = 4; + + WorkloadSpec spec = 5; +} + +// WorkloadSpec parallels Pod, but with far fewer configurable fields. +message WorkloadSpec { + repeated Container containers = 1; +} + +message Container { + string name = 1; +} + +message RunWorkloadResponse { +} + +message CheckpointWorkloadRequest { + string actor_template_namespace = 1; + string actor_template_name = 2; + string actor_id = 3; + + string runsc_path = 4; + + WorkloadSpec spec = 5; + + // An object storage URI prefix below which the checkpoint data will be + // stored. + // + // The structure of the checkpoint should generally be treated as opaque. For + // gVisor, the checkpoint consists of a checkpoint.img file that contains the + // memory, sentry state, and filesystem deltas. + // + // For example: "gs://bucket/actors/1234/snapshots/5678/" + string snapshot_uri_prefix = 6; +} + +message CheckpointWorkloadResponse { + +} + +message RestoreWorkloadRequest { + string actor_template_namespace = 1; + string actor_template_name = 2; + string actor_id = 3; + + string runsc_path = 4; + + WorkloadSpec spec = 5; + + // The object storage URI prefix of the snapshot to restore. + string snapshot_uri_prefix = 6; +} + +message RestoreWorkloadResponse { + +} diff --git a/proto/ateompb/ateom_grpc.pb.go b/proto/ateompb/ateom_grpc.pb.go new file mode 100644 index 000000000..e6f5f5ac5 --- /dev/null +++ b/proto/ateompb/ateom_grpc.pb.go @@ -0,0 +1,255 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc v4.25.3 +// source: ateom.proto + +package ateompb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Ateom_RunWorkload_FullMethodName = "/ateom.Ateom/RunWorkload" + Ateom_CheckpointWorkload_FullMethodName = "/ateom.Ateom/CheckpointWorkload" + Ateom_RestoreWorkload_FullMethodName = "/ateom.Ateom/RestoreWorkload" +) + +// AteomClient is the client API for Ateom service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// Ateom is the interface to control a single gVisor (or, in the future microVM) +// guest inside a worker pod. +// +// Each ateom server has two main states, "available" and "executing". +// +// When the ateom is "available", the substrate control plane is free to either +// boot a new workload (using RunWorkload), or restore an existing workload from +// a checkpoint (using RestoreWorkload). These calls move the ateom into +// "executing" state. +// +// When the ateom is "executing", the substrate control plane can checkpoint the +// running workload (with CheckpointWorkload). This moves the ateom back to +// "free" state. +type AteomClient interface { + // RunWorkload tells ateom to begin running a new workload (one or more + // containers, potentially with shared filesystems). + RunWorkload(ctx context.Context, in *RunWorkloadRequest, opts ...grpc.CallOption) (*RunWorkloadResponse, error) + // CheckpointWorkload tells ateom to save the current state of the running + // workload to object storage, and then completely reset itself to a blank + // state (back to "available" state.) + CheckpointWorkload(ctx context.Context, in *CheckpointWorkloadRequest, opts ...grpc.CallOption) (*CheckpointWorkloadResponse, error) + // RestoreWorkload restores a workload from checkpoint that was previously + // written by CheckpointWorkload. Ateom will handle downloading the correct + // gVisor / runsc version to match the checkpoint. + RestoreWorkload(ctx context.Context, in *RestoreWorkloadRequest, opts ...grpc.CallOption) (*RestoreWorkloadResponse, error) +} + +type ateomClient struct { + cc grpc.ClientConnInterface +} + +func NewAteomClient(cc grpc.ClientConnInterface) AteomClient { + return &ateomClient{cc} +} + +func (c *ateomClient) RunWorkload(ctx context.Context, in *RunWorkloadRequest, opts ...grpc.CallOption) (*RunWorkloadResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RunWorkloadResponse) + err := c.cc.Invoke(ctx, Ateom_RunWorkload_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ateomClient) CheckpointWorkload(ctx context.Context, in *CheckpointWorkloadRequest, opts ...grpc.CallOption) (*CheckpointWorkloadResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CheckpointWorkloadResponse) + err := c.cc.Invoke(ctx, Ateom_CheckpointWorkload_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *ateomClient) RestoreWorkload(ctx context.Context, in *RestoreWorkloadRequest, opts ...grpc.CallOption) (*RestoreWorkloadResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RestoreWorkloadResponse) + err := c.cc.Invoke(ctx, Ateom_RestoreWorkload_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AteomServer is the server API for Ateom service. +// All implementations must embed UnimplementedAteomServer +// for forward compatibility. +// +// Ateom is the interface to control a single gVisor (or, in the future microVM) +// guest inside a worker pod. +// +// Each ateom server has two main states, "available" and "executing". +// +// When the ateom is "available", the substrate control plane is free to either +// boot a new workload (using RunWorkload), or restore an existing workload from +// a checkpoint (using RestoreWorkload). These calls move the ateom into +// "executing" state. +// +// When the ateom is "executing", the substrate control plane can checkpoint the +// running workload (with CheckpointWorkload). This moves the ateom back to +// "free" state. +type AteomServer interface { + // RunWorkload tells ateom to begin running a new workload (one or more + // containers, potentially with shared filesystems). + RunWorkload(context.Context, *RunWorkloadRequest) (*RunWorkloadResponse, error) + // CheckpointWorkload tells ateom to save the current state of the running + // workload to object storage, and then completely reset itself to a blank + // state (back to "available" state.) + CheckpointWorkload(context.Context, *CheckpointWorkloadRequest) (*CheckpointWorkloadResponse, error) + // RestoreWorkload restores a workload from checkpoint that was previously + // written by CheckpointWorkload. Ateom will handle downloading the correct + // gVisor / runsc version to match the checkpoint. + RestoreWorkload(context.Context, *RestoreWorkloadRequest) (*RestoreWorkloadResponse, error) + mustEmbedUnimplementedAteomServer() +} + +// UnimplementedAteomServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAteomServer struct{} + +func (UnimplementedAteomServer) RunWorkload(context.Context, *RunWorkloadRequest) (*RunWorkloadResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RunWorkload not implemented") +} +func (UnimplementedAteomServer) CheckpointWorkload(context.Context, *CheckpointWorkloadRequest) (*CheckpointWorkloadResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CheckpointWorkload not implemented") +} +func (UnimplementedAteomServer) RestoreWorkload(context.Context, *RestoreWorkloadRequest) (*RestoreWorkloadResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RestoreWorkload not implemented") +} +func (UnimplementedAteomServer) mustEmbedUnimplementedAteomServer() {} +func (UnimplementedAteomServer) testEmbeddedByValue() {} + +// UnsafeAteomServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AteomServer will +// result in compilation errors. +type UnsafeAteomServer interface { + mustEmbedUnimplementedAteomServer() +} + +func RegisterAteomServer(s grpc.ServiceRegistrar, srv AteomServer) { + // If the following call panics, it indicates UnimplementedAteomServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Ateom_ServiceDesc, srv) +} + +func _Ateom_RunWorkload_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RunWorkloadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AteomServer).RunWorkload(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Ateom_RunWorkload_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AteomServer).RunWorkload(ctx, req.(*RunWorkloadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Ateom_CheckpointWorkload_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckpointWorkloadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AteomServer).CheckpointWorkload(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Ateom_CheckpointWorkload_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AteomServer).CheckpointWorkload(ctx, req.(*CheckpointWorkloadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Ateom_RestoreWorkload_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RestoreWorkloadRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AteomServer).RestoreWorkload(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Ateom_RestoreWorkload_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AteomServer).RestoreWorkload(ctx, req.(*RestoreWorkloadRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Ateom_ServiceDesc is the grpc.ServiceDesc for Ateom service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Ateom_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ateom.Ateom", + HandlerType: (*AteomServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "RunWorkload", + Handler: _Ateom_RunWorkload_Handler, + }, + { + MethodName: "CheckpointWorkload", + Handler: _Ateom_CheckpointWorkload_Handler, + }, + { + MethodName: "RestoreWorkload", + Handler: _Ateom_RestoreWorkload_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ateom.proto", +} diff --git a/proto/ateompb/gen.go b/proto/ateompb/gen.go new file mode 100644 index 000000000..616c7cb9a --- /dev/null +++ b/proto/ateompb/gen.go @@ -0,0 +1,17 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ateompb + +//go:generate bash -c "../../hack/protoc.sh --plugin=protoc-gen-go=$(bash ../../hack/run-tool.sh --print-bin-path protoc-gen-go) --plugin=protoc-gen-go-grpc=$(bash ../../hack/run-tool.sh --print-bin-path protoc-gen-go-grpc) --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. ateom.proto"