From 7b6d66908beb7d25169b0a6de0b53c25ea8b6b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alby=20Hern=C3=A1ndez?= Date: Tue, 13 Aug 2024 00:13:43 +0100 Subject: [PATCH] First commit --- .github/workflows/release-binaries.yaml | 2 +- .github/workflows/release-charts.yaml | 2 +- Dockerfile | 6 +- Makefile | 8 +- README.md | 115 +++++----- api/v1alpha1/config_types.go | 66 +++--- charts/bucket-simple-server/Chart.yaml | 20 ++ .../templates/_helpers.tpl | 20 +- .../templates/configmap.yaml | 11 + .../templates/deployment.yaml | 16 +- .../templates/serviceaccount.yaml | 4 +- .../values.yaml | 10 +- charts/hitman/Chart.yaml | 21 -- charts/hitman/templates/clusterrole.yaml | 18 -- .../hitman/templates/clusterrolebinding.yaml | 22 -- charts/hitman/templates/configmap.yaml | 11 - cmd/main.go | 2 +- docs/prototypes/config.yaml | 37 +++ docs/prototypes/hitman.yaml | 43 ---- go.mod | 45 +++- go.sum | 153 +++++++++++++ internal/cmd/cmd.go | 4 +- internal/cmd/help/help.go | 2 +- internal/cmd/run/run.go | 53 +++-- internal/cmd/version/version.go | 2 +- internal/config/config.go | 8 +- internal/globals/globals.go | 8 +- internal/kubernetes/kubernetes.go | 26 --- internal/processor/processor.go | 214 +++++++----------- internal/template/functions.go | 165 -------------- 30 files changed, 508 insertions(+), 606 deletions(-) create mode 100644 charts/bucket-simple-server/Chart.yaml rename charts/{hitman => bucket-simple-server}/templates/_helpers.tpl (71%) create mode 100644 charts/bucket-simple-server/templates/configmap.yaml rename charts/{hitman => bucket-simple-server}/templates/deployment.yaml (82%) rename charts/{hitman => bucket-simple-server}/templates/serviceaccount.yaml (64%) rename charts/{hitman => bucket-simple-server}/values.yaml (91%) delete mode 100644 charts/hitman/Chart.yaml delete mode 100644 charts/hitman/templates/clusterrole.yaml delete mode 100644 charts/hitman/templates/clusterrolebinding.yaml delete mode 100644 charts/hitman/templates/configmap.yaml create mode 100644 docs/prototypes/config.yaml delete mode 100644 docs/prototypes/hitman.yaml delete mode 100644 internal/kubernetes/kubernetes.go delete mode 100644 internal/template/functions.go diff --git a/.github/workflows/release-binaries.yaml b/.github/workflows/release-binaries.yaml index 334419c..a20435e 100644 --- a/.github/workflows/release-binaries.yaml +++ b/.github/workflows/release-binaries.yaml @@ -70,7 +70,7 @@ jobs: run: | export GOOS=${{ matrix.goos }} export GOARCH=${{ matrix.goarch }} - export PACKAGE_NAME=hitman-${{ steps.read_tag.outputs.release_tag }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz + export PACKAGE_NAME=bss-${{ steps.read_tag.outputs.release_tag }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz make package make package-signature diff --git a/.github/workflows/release-charts.yaml b/.github/workflows/release-charts.yaml index 781b2b3..213f658 100644 --- a/.github/workflows/release-charts.yaml +++ b/.github/workflows/release-charts.yaml @@ -39,6 +39,6 @@ jobs: config: .github/chart-releaser-config.yaml env: CR_OWNER: "$GITHUB_REPOSITORY_OWNER" - CR_GIT_REPO: hitman + CR_GIT_REPO: bucket-simple-server CR_SKIP_EXISTING: true CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/Dockerfile b/Dockerfile index 5d36abc..de0e2bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,13 +19,13 @@ COPY ./ . # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. -RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o hitman ./cmd +RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o bss ./cmd # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details FROM gcr.io/distroless/static:nonroot WORKDIR / -COPY --from=builder /workspace/hitman . +COPY --from=builder /workspace/bss . USER 65532:65532 -ENTRYPOINT ["/hitman"] \ No newline at end of file +ENTRYPOINT ["/bss"] \ No newline at end of file diff --git a/Makefile b/Makefile index 2ca30c4..d534351 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Image URL to use all building/pushing image targets -IMG ?= ghcr.io/prosimcorp/hitman:latest +IMG ?= ghcr.io/freepik-company/bucket-simple-server:latest # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -83,7 +83,7 @@ check-go-target: ## Check presente of GOOS and GOARCH vars. .PHONY: build build: fmt vet check-go-target ## Build CLI binary. - go build -o bin/hitman-$(GOOS)-$(GOARCH) cmd/main.go + go build -o bin/bss-$(GOOS)-$(GOARCH) cmd/main.go .PHONY: run run: fmt vet ## Run a controller from your host. @@ -125,9 +125,9 @@ package: check-go-target ## Package binary. @mkdir -p dist @if [ "$(OS)" = "linux" ]; then \ - tar --transform="s/hitman-$(GOOS)-$(GOARCH)/hitman/" -cvzf dist/$(PACKAGE_NAME) -C bin hitman-$(GOOS)-$(GOARCH) -C ../ LICENSE README.md; \ + tar --transform="s/bss-$(GOOS)-$(GOARCH)/bss/" -cvzf dist/$(PACKAGE_NAME) -C bin bss-$(GOOS)-$(GOARCH) -C ../ LICENSE README.md; \ elif [ "$(OS)" = "darwin" ]; then \ - tar -cvzf dist/$(PACKAGE_NAME) -s '/hitman-$(GOOS)-$(GOARCH)/hitman/' -C bin hitman-$(GOOS)-$(GOARCH) -C ../ LICENSE README.md; \ + tar -cvzf dist/$(PACKAGE_NAME) -s '/bss-$(GOOS)-$(GOARCH)/bss/' -C bin bss-$(GOOS)-$(GOARCH) -C ../ LICENSE README.md; \ else \ echo "Unsupported OS: $(GOOS)"; \ exit 1; \ diff --git a/README.md b/README.md index 5beea35..13ac23f 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,21 @@ -# Hitman +# Bucket Simple Server -![GitHub go.mod Go version (subdirectory of monorepo)](https://img.shields.io/github/go-mod/go-version/achetronic/hitman) -![GitHub](https://img.shields.io/github/license/achetronic/hitman) +![GitHub go.mod Go version (subdirectory of monorepo)](https://img.shields.io/github/go-mod/go-version/freepik-company/bucket-simple-server) +![GitHub](https://img.shields.io/github/license/freepik-company/bucket-simple-server) ![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCeSb3yfsPNNVr13YsYNvCAw?label=achetronic&link=http%3A%2F%2Fyoutube.com%2Fachetronic) ![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/achetronic?style=flat&logo=twitter&link=https%3A%2F%2Ftwitter.com%2Fachetronic) -A daemon for Kubernetes to kill target resources under user-defined templated conditions +A tiny server to safely expose some routes from your buckets without sharing cloud credentials ## Motivation -In today's fast-paced environments, Kubernetes clusters often manage systems that dynamically create and destroy resources automatically. Examples of these are pipelines and cronjobs. +This project was created to solve a common problem: securely sharing reports and small files without exposing an entire storage bucket. -However, these automated processes can sometimes get stuck, causing disruptions that affect the smooth operation of the entire system. Often, simply terminating some of these objects can restore normalcy. +Setting up a complex proxy like Envoy is time-consuming and often requires crafting custom plugins to connect to different storage services. While Envoy is great for large-scale projects, this lightweight solution is perfect for smaller needs, such as automated +reports, etc. -There is a need for a solution that empowers Kubernetes administrators to automate this cleanup process efficiently. -This project exists to provide a robust agent for automating the deletion of potential stuck resources, -ensuring your Kubernetes clusters run smoothly and reliably. +It’s simple, focused, and easy to use, making secure file sharing much easier. ## Flags @@ -25,16 +24,16 @@ They are described in the following table: | Name | Description | Default | Example | |:------------------|:-------------------------------|:-------------:|:-------------------------| -| `--config` | Path to the YAML config file | `hitman.yaml` | `--config ./hitman.yaml` | +| `--config` | Path to the YAML config file | `config.yaml` | `--config ./config.yaml` | | `--log-level` | Verbosity level for logs | `info` | `--log-level info` | | `--disable-trace` | Disable showing traces in logs | `info` | `--log-level info` | > Output is thrown always in JSON as it is more suitable for automations ```console -hitman run \ +bss run \ --log-level=info - --config="./hitman.yaml" + --config="./config.yaml" ``` ## Examples @@ -45,48 +44,42 @@ Here you have a complete example. More up-to-date one will always be maintained ```yaml version: v1alpha1 -kind: Hitman +kind: Config metadata: - name: killing-sample + name: access-to-reports spec: - synchronization: - time: 1m - - resources: - - - target: - group: "" - version: v1 - resource: pods - - # Select the resources by their name - # Choose one of the following options - name: - matchRegex: ^(coredns-) - #matchExact: "coredns-xxxxxxxxxx-yyyyy" - - # Select the namespace where the resources are located - # Choose one of the following options - namespace: - matchRegex: ^(kube-system) - #matchExact: kube-system - - conditions: - - # Delete the resources when they are older than 10 minutes - - key: |- - {{/* Define some variables */}} - {{- $maxAgeMinutes := 10 -}} - - {{- $nowTimestamp := (now | unixEpoch) -}} - {{- $podStartTime := (toDate "2006-01-02T15:04:05Z07:00" .object.status.startTime) | unixEpoch -}} - - {{/* Calculate the age of the resource in minutes */}} - {{- $minutedFromNow := int (round (div (sub $nowTimestamp $podStartTime) 60) 0) -}} - - {{/* Print true ONLY if the resource is older than 5 minutes */}} - {{- printf "%v" (ge $minutedFromNow $maxAgeMinutes) -}} - value: true + # Source of data to be served. + # This section can be extended to support other sources like S3, Azure Blob Storage, etc. + source: + gcs: + bucket: general-purposes-bucket + credentials: + path: /tmp/credentials.json + + # Web server configuration + # Here it's the place to define the server configuration like port, host, credentials, etc. + webServer: + listener: + port: 9090 + host: localhost + + # Several credentials can be defined + credentials: + - type: "bearer" + token: "12345xxxx12345" + + - type: "bearer" + token: "6789yyyy6789" + + - type: "bearer" + token: "${TOKEN_FROM_ENV}" + + # Routes must be defined to allow access to the data + # They are defined as golang regular expressions + # Remember: negative lookbehind is not supported + allowedTargets: + - route: "^/qa-reports/(.*).json$" + - route: "^/pipelines-results/(.*).json$" ``` @@ -95,31 +88,31 @@ spec: ## How to deploy -This project is designed specially for Kubernetes, but also provides binary files +This project can be deployed in Kubernetes, but also provides binary files and Docker images to make it easy to be deployed however wanted ### Binaries -Binary files for most popular platforms will be added to the [releases](https://github.com/achetronic/hitman/releases) +Binary files for most popular platforms will be added to the [releases](https://github.com/freepik-company/bucket-simple-server/releases) ### Kubernetes -You can deploy `hitman` in Kubernetes using Helm as follows: +You can deploy `bucket-simple-server` in Kubernetes using Helm as follows: ```console -helm repo add hitman https://achetronic.github.io/hitman/ +helm repo add bucket-simple-server https://freepik-company.github.io/bucket-simple-server/ -helm upgrade --install --wait hitman \ - --namespace hitman \ - --create-namespace achetronic/hitman +helm upgrade --install --wait bucket-simple-server \ + --namespace bucket-simple-server \ + --create-namespace freepik-company/bucket-simple-server ``` -> More information and Helm packages [here](https://achetronic.github.io/hitman/) +> More information and Helm packages [here](https://freepik-company.github.io/bucket-simple-server/) ### Docker -Docker images can be found in GitHub's [packages](https://github.com/achetronic/hitman/pkgs/container/hitman) +Docker images can be found in GitHub's [packages](https://github.com/freepik-company/bucket-simple-server/pkgs/container/bucket-simple-server) related to this repository > Do you need it in a different container registry? I think this is not needed, but if I'm wrong, please, let's discuss diff --git a/api/v1alpha1/config_types.go b/api/v1alpha1/config_types.go index a7df13f..108bacf 100644 --- a/api/v1alpha1/config_types.go +++ b/api/v1alpha1/config_types.go @@ -16,50 +16,58 @@ limitations under the License. package v1alpha1 -// TargetNameT defines TODO -type TargetSelectorT struct { - MatchExact string `yaml:"matchExact,omitempty"` - MatchRegex string `yaml:"matchRegex,omitempty"` +// MetadataT TODO +type MetadataT struct { + Name string `yaml:"name"` } -// TargetT defines TODO -type TargetT struct { - Group string `yaml:"group"` - Version string `yaml:"version"` - Resource string `yaml:"resource"` - Name TargetSelectorT `yaml:"name"` - Namespace TargetSelectorT `yaml:"namespace"` +// GoogleContentStorageCredentialsT TODO +type GoogleContentStorageCredentialsT struct { + Path string `yaml:"path"` } -// ConditionT defines TODO -type ConditionT struct { - Key string `yaml:"key"` - Value string `yaml:"value"` +// ConditionT TODO +type GoogleContentStorageT struct { + Bucket string `yaml:"bucket"` + Credentials GoogleContentStorageCredentialsT `yaml:"credentials"` } -// ResourceT defines TODO -type ResourceT struct { - Target TargetT `yaml:"target"` - Conditions []ConditionT `yaml:"conditions"` +// SourceT TODO +type SourceT struct { + GCS GoogleContentStorageT `yaml:"gcs"` } -// MetadataSpec TODO -type MetadataT struct { - Name string `yaml:"name"` +// ListenerT TODO +type ListenerT struct { + Port int `yaml:"port"` + Host string `yaml:"host"` +} + +// CredentialT TODO +type CredentialT struct { + Type string `yaml:"type"` + Token string `yaml:"token"` +} + +// AllowedTargetT TODO +type AllowedTargetT struct { + Route string `yaml:"route"` } -// SynchronizationT defines TODO -type SynchronizationT struct { - Time string `yaml:"time"` +// WebserverT TODO +type WebserverT struct { + Listener ListenerT `yaml:"listener"` + Credentials []CredentialT `yaml:"credentials"` + AllowedTargets []AllowedTargetT `yaml:"allowedTargets"` } -// SpecificationSpec TODO +// SpecificationT TODO type SpecificationT struct { - Synchronization SynchronizationT `yaml:"synchronization"` - Resources []ResourceT `yaml:"resources"` + Source SourceT `yaml:"source"` + Webserver WebserverT `yaml:"webServer"` } -// ConfigSpec TODO +// ConfigT TODO type ConfigT struct { ApiVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` diff --git a/charts/bucket-simple-server/Chart.yaml b/charts/bucket-simple-server/Chart.yaml new file mode 100644 index 0000000..9513973 --- /dev/null +++ b/charts/bucket-simple-server/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +name: bucketSimpleServer +type: application +description: >- + A Helm chart for bucketSimpleServer, a tiny server to safely expose + some routes on from buckets without sharing cloud credentials +version: 0.1.0 # chart version +appVersion: "0.1.0" # application version +kubeVersion: ">=1.22.0-0" # kubernetes version +home: https://github.com/freepik-company/bucketSimpleServer +sources: + - https://github.com/freepik-company/bucketSimpleServer +keywords: + - bucketSimpleServer + - bucket +maintainers: + - name: Alby Hernández + email: ahernandez@freepik.com + url: https://github.com/achetronic/ + diff --git a/charts/hitman/templates/_helpers.tpl b/charts/bucket-simple-server/templates/_helpers.tpl similarity index 71% rename from charts/hitman/templates/_helpers.tpl rename to charts/bucket-simple-server/templates/_helpers.tpl index 6a585e9..0934509 100644 --- a/charts/hitman/templates/_helpers.tpl +++ b/charts/bucket-simple-server/templates/_helpers.tpl @@ -1,7 +1,7 @@ {{/* Expand the name of the chart. */}} -{{- define "hitman.name" -}} +{{- define "bucketSimpleServer.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} @@ -10,7 +10,7 @@ Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} -{{- define "hitman.fullname" -}} +{{- define "bucketSimpleServer.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} @@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name. {{/* Create chart name and version as used by the chart label. */}} -{{- define "hitman.chart" -}} +{{- define "bucketSimpleServer.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} -{{- define "hitman.labels" -}} -helm.sh/chart: {{ include "hitman.chart" . }} -{{ include "hitman.selectorLabels" . }} +{{- define "bucketSimpleServer.labels" -}} +helm.sh/chart: {{ include "bucketSimpleServer.chart" . }} +{{ include "bucketSimpleServer.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} @@ -45,17 +45,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} {{/* Selector labels */}} -{{- define "hitman.selectorLabels" -}} -app.kubernetes.io/name: {{ include "hitman.name" . }} +{{- define "bucketSimpleServer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "bucketSimpleServer.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} -{{- define "hitman.serviceAccountName" -}} +{{- define "bucketSimpleServer.serviceAccountName" -}} {{- if .Values.agent.serviceAccount.create }} -{{- default (include "hitman.fullname" .) .Values.agent.serviceAccount.name }} +{{- default (include "bucketSimpleServer.fullname" .) .Values.agent.serviceAccount.name }} {{- else }} {{- default "default" .Values.agent.serviceAccount.name }} {{- end }} diff --git a/charts/bucket-simple-server/templates/configmap.yaml b/charts/bucket-simple-server/templates/configmap.yaml new file mode 100644 index 0000000..c31a8b6 --- /dev/null +++ b/charts/bucket-simple-server/templates/configmap.yaml @@ -0,0 +1,11 @@ +{{ if .Values.agent.config }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "bucketSimpleServer.fullname" . }}-agent-config + labels: + {{- include "bucketSimpleServer.labels" . | nindent 4 }} +data: + bucketSimpleServer.yaml: |- + {{- .Values.agent.config | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/hitman/templates/deployment.yaml b/charts/bucket-simple-server/templates/deployment.yaml similarity index 82% rename from charts/hitman/templates/deployment.yaml rename to charts/bucket-simple-server/templates/deployment.yaml index 91b3b06..4a0c830 100644 --- a/charts/hitman/templates/deployment.yaml +++ b/charts/bucket-simple-server/templates/deployment.yaml @@ -1,14 +1,14 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "hitman.fullname" . }} + name: {{ include "bucketSimpleServer.fullname" . }} labels: - {{- include "hitman.labels" . | nindent 4 }} + {{- include "bucketSimpleServer.labels" . | nindent 4 }} spec: replicas: {{ .Values.agent.replicaCount }} selector: matchLabels: - {{- include "hitman.selectorLabels" . | nindent 6 }} + {{- include "bucketSimpleServer.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.agent.podAnnotations }} @@ -16,13 +16,13 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "hitman.selectorLabels" . | nindent 8 }} + {{- include "bucketSimpleServer.selectorLabels" . | nindent 8 }} spec: {{- with .Values.agent.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - serviceAccountName: {{ include "hitman.serviceAccountName" . }} + serviceAccountName: {{ include "bucketSimpleServer.serviceAccountName" . }} securityContext: {{- toYaml .Values.agent.podSecurityContext | nindent 8 }} containers: @@ -30,10 +30,10 @@ spec: image: "{{ .Values.agent.image.repository }}:{{ .Values.agent.image.tag | default (printf "v%s" .Chart.AppVersion) }}" imagePullPolicy: {{ .Values.agent.image.pullPolicy }} command: - - /hitman + - /bucketSimpleServer - run - --config - - /etc/agent/hitman.yaml + - /etc/agent/bucketSimpleServer.yaml {{- with .Values.agent.extraArgs }} args: @@ -89,7 +89,7 @@ spec: volumes: - name: agent-config configMap: - name: {{ include "hitman.fullname" . }}-agent-config + name: {{ include "bucketSimpleServer.fullname" . }}-agent-config {{- with .Values.agent.extraVolumes }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/charts/hitman/templates/serviceaccount.yaml b/charts/bucket-simple-server/templates/serviceaccount.yaml similarity index 64% rename from charts/hitman/templates/serviceaccount.yaml rename to charts/bucket-simple-server/templates/serviceaccount.yaml index 35b4b31..53ce3c8 100644 --- a/charts/hitman/templates/serviceaccount.yaml +++ b/charts/bucket-simple-server/templates/serviceaccount.yaml @@ -2,9 +2,9 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: {{ include "hitman.serviceAccountName" . }} + name: {{ include "bucketSimpleServer.serviceAccountName" . }} labels: - {{- include "hitman.labels" . | nindent 4 }} + {{- include "bucketSimpleServer.labels" . | nindent 4 }} {{- with .Values.agent.serviceAccount.annotations }} annotations: {{- toYaml . | nindent 4 }} diff --git a/charts/hitman/values.yaml b/charts/bucket-simple-server/values.yaml similarity index 91% rename from charts/hitman/values.yaml rename to charts/bucket-simple-server/values.yaml index f6d71b8..8be4ba7 100644 --- a/charts/hitman/values.yaml +++ b/charts/bucket-simple-server/values.yaml @@ -1,4 +1,4 @@ -# Default values for hitman. +# Default values for Bucket Simple Server. nameOverride: "" fullnameOverride: "" @@ -28,7 +28,7 @@ agent: # Specify the configuration config: | # A complete example in the upstream repository - # Ref: https://github.com/achetronic/hitman + # Ref: https://github.com/freepik-company/bucketSimpleServer serviceAccount: # Specifies whether a service account should be created @@ -37,12 +37,12 @@ agent: annotations: { } # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template - name: "hitman" + name: "bucketSimpleServer" replicaCount: 1 image: - repository: ghcr.io/achetronic/hitman + repository: ghcr.io/freepik-company/bucketSimpleServer pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "v0.1.0" @@ -50,7 +50,7 @@ agent: imagePullSecrets: [] # Extra args to pass to the agent. - # Ref: https://github.com/achetronic/hitman?tab=readme-ov-file#flags + # Ref: https://github.com/freepik-company/bucketSimpleServer?tab=readme-ov-file#flags # Example: # - --log-level=debug extraArgs: [] diff --git a/charts/hitman/Chart.yaml b/charts/hitman/Chart.yaml deleted file mode 100644 index 00d959c..0000000 --- a/charts/hitman/Chart.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# PG Selector -apiVersion: v2 -name: hitman -type: application -description: >- - A Helm chart for Hitman, a daemon for Kubernetes to kill - target resources under user-defined templated conditions -version: 0.1.0 # chart version -appVersion: "0.1.0" # pg-selector version -kubeVersion: ">=1.22.0-0" # kubernetes version -home: https://github.com/achetronic/hitman -sources: - - https://github.com/achetronic/hitman -keywords: - - hitman - - kubernetes -maintainers: - - name: Alby Hernández - email: donfumero@gmail.com.com - url: https://github.com/achetronic/hitman - diff --git a/charts/hitman/templates/clusterrole.yaml b/charts/hitman/templates/clusterrole.yaml deleted file mode 100644 index 673454a..0000000 --- a/charts/hitman/templates/clusterrole.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if (.Values.customClusterRole.create) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "hitman.fullname" . }}-custom - labels: - {{- include "hitman.labels" . | nindent 4 }} - {{- if .Values.customClusterRole.annotations }} - annotations: - {{- range $key, $value := .Values.customClusterRole.annotations }} - {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} - {{- end }} - {{- end }} -rules: - {{- if .Values.customClusterRole.rules -}} - {{ toYaml .Values.customClusterRole.rules | nindent 2 -}} - {{- end }} -{{- end }} diff --git a/charts/hitman/templates/clusterrolebinding.yaml b/charts/hitman/templates/clusterrolebinding.yaml deleted file mode 100644 index 469a265..0000000 --- a/charts/hitman/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if (.Values.customClusterRole.create) -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "hitman.fullname" . }}-custom - labels: - {{- include "hitman.labels" . | nindent 4 }} - {{- if .Values.customClusterRole.clusterRoleBinding.annotations }} - annotations: - {{- range $key, $value := .Values.customClusterRole.clusterRoleBinding.annotations }} - {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }} - {{- end }} - {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "hitman.fullname" . }}-custom -subjects: - - kind: ServiceAccount - name: {{ include "hitman.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/charts/hitman/templates/configmap.yaml b/charts/hitman/templates/configmap.yaml deleted file mode 100644 index 9048bef..0000000 --- a/charts/hitman/templates/configmap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{ if .Values.agent.config }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "hitman.fullname" . }}-agent-config - labels: - {{- include "hitman.labels" . | nindent 4 }} -data: - hitman.yaml: |- - {{- .Values.agent.config | nindent 4 }} -{{- end }} \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go index 6f74870..421519d 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,7 +4,7 @@ import ( "os" "path/filepath" - "hitman/internal/cmd" + "bucket-simple-server/internal/cmd" ) func main() { diff --git a/docs/prototypes/config.yaml b/docs/prototypes/config.yaml new file mode 100644 index 0000000..a771dd2 --- /dev/null +++ b/docs/prototypes/config.yaml @@ -0,0 +1,37 @@ +version: v1alpha1 +kind: Config +metadata: + name: access-to-reports +spec: + # Source of data to be served. + # This section can be extended to support other sources like S3, Azure Blob Storage, etc. + source: + gcs: + bucket: general-purposes-bucket + credentials: + path: /tmp/credentials.json + + # Web server configuration + # Here it's the place to define the server configuration like port, host, credentials, etc. + webServer: + listener: + port: 9090 + host: localhost + + # Several credentials can be defined + credentials: + - type: "bearer" + token: "12345xxxx12345" + + - type: "bearer" + token: "6789yyyy6789" + + - type: "bearer" + token: "${TOKEN_FROM_ENV}" + + # Routes must be defined to allow access to the data + # They are defined as golang regular expressions + # Remember: negative lookbehind is not supported + allowedTargets: + - route: "^/qa-reports/(.*).json$" + - route: "^/pipelines-results/(.*).json$" diff --git a/docs/prototypes/hitman.yaml b/docs/prototypes/hitman.yaml deleted file mode 100644 index fbb1e70..0000000 --- a/docs/prototypes/hitman.yaml +++ /dev/null @@ -1,43 +0,0 @@ -version: v1alpha1 -kind: Hitman -metadata: - name: killing-sample -spec: - synchronization: - time: 1m - - resources: - - - target: - group: "" - version: v1 - resource: pods - - # Select the resources by their name - # Choose one of the following options - name: - matchRegex: ^(coredns-) - #matchExact: "coredns-xxxxxxxxxx-yyyyy" - - # Select the namespace where the resources are located - # Choose one of the following options - namespace: - matchRegex: ^(kube-system) - #matchExact: kube-system - - conditions: - - # Delete the resources when they are older than 10 minutes - - key: |- - {{/* Define some variables */}} - {{- $maxAgeMinutes := 10 -}} - - {{- $nowTimestamp := (now | unixEpoch) -}} - {{- $podStartTime := (toDate "2006-01-02T15:04:05Z07:00" .object.status.startTime) | unixEpoch -}} - - {{/* Calculate the age of the resource in minutes */}} - {{- $minutedFromNow := int (round (div (sub $nowTimestamp $podStartTime) 60) 0) -}} - - {{/* Print true ONLY if the resource is older than 5 minutes */}} - {{- printf "%v" (ge $minutedFromNow $maxAgeMinutes) -}} - value: true diff --git a/go.mod b/go.mod index 13ba2c2..64194ba 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module hitman +module bucket-simple-server go 1.22.0 @@ -17,6 +17,12 @@ require ( ) require ( + cloud.google.com/go v0.115.0 // indirect + cloud.google.com/go/auth v0.6.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect + cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/iam v1.1.8 // indirect + cloud.google.com/go/storage v1.43.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -24,8 +30,10 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect @@ -35,7 +43,10 @@ require ( github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.5 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -54,18 +65,30 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.21.0 // indirect + golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/api v0.187.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect + google.golang.org/grpc v1.64.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/api v0.30.3 // indirect diff --git a/go.sum b/go.sum index 9ff2a89..89c4a9e 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,17 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.6.1 h1:T0Zw1XM5c1GlpN2HYr2s+m3vr1p2wy+8VN+Z1FKxW38= +cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= +cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= +cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= +cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= +cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -8,8 +22,11 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= 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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -17,14 +34,23 @@ 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/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +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/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +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.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/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.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -37,14 +63,34 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +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.1/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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +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.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -53,8 +99,17 @@ 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/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= @@ -99,6 +154,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= @@ -123,6 +179,19 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= 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= @@ -132,55 +201,137 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/api v0.187.0 h1:Mxs7VATVC2v7CY+7Xwm4ndkX71hpElcvx0D1Ji/p1eo= +google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +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/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls= +google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +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/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +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= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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= @@ -192,6 +343,8 @@ 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= +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/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ= k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04= k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index efed804..969b0ba 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" - "hitman/internal/cmd/run" - "hitman/internal/cmd/version" + "bucket-simple-server/internal/cmd/run" + "bucket-simple-server/internal/cmd/version" ) const ( diff --git a/internal/cmd/help/help.go b/internal/cmd/help/help.go index d980a2c..3c43933 100644 --- a/internal/cmd/help/help.go +++ b/internal/cmd/help/help.go @@ -11,7 +11,7 @@ const ( descriptionLong = ` Help provides help for any command in the application. - Simply type hitman help [path to command] for full details.` + Simply type bucket-simple-server help [path to command] for full details.` ) func NewCommand() *cobra.Command { diff --git a/internal/cmd/run/run.go b/internal/cmd/run/run.go index 30ee3f4..7d4f974 100644 --- a/internal/cmd/run/run.go +++ b/internal/cmd/run/run.go @@ -1,11 +1,13 @@ package run import ( + "bucket-simple-server/internal/config" + "bucket-simple-server/internal/globals" + "bucket-simple-server/internal/processor" "fmt" - "hitman/internal/config" - "hitman/internal/globals" - "hitman/internal/processor" "log" + "net/http" + "strconv" "time" "github.com/spf13/cobra" @@ -41,7 +43,7 @@ func NewCommand() *cobra.Command { // cmd.Flags().String("log-level", "info", "Verbosity level for logs") cmd.Flags().Bool("disable-trace", true, "Disable showing traces in logs") - cmd.Flags().String("config", "hitman.yaml", "Path to the YAML config file") + cmd.Flags().String("config", "bucket-simple-server.yaml", "Path to the YAML config file") return cmd } @@ -60,7 +62,7 @@ func RunCommand(cmd *cobra.Command, args []string) { if err != nil { log.Fatalf(LogLevelFlagErrorMessage, err) } - globals.ExecContext.LogLevel = logLevelFlag + globals.Application.LogLevel = logLevelFlag disableTraceFlag, err := cmd.Flags().GetBool("disable-trace") if err != nil { @@ -76,35 +78,40 @@ func RunCommand(cmd *cobra.Command, args []string) { // EXECUTION FLOW RELATED ///////////////////////////// - globals.ExecContext.Logger.Infof("starting Hitman. Getting ready to kill some targets") + globals.Application.Logger.Infof("starting BucketSimpleServer. Getting ready.") // Parse and store the config configContent, err := config.ReadFile(configPath) if err != nil { - globals.ExecContext.Logger.Fatalf(fmt.Sprintf(ConfigNotParsedErrorMessage, err)) + globals.Application.Logger.Fatalf(fmt.Sprintf(ConfigNotParsedErrorMessage, err)) } - globals.ExecContext.Config = configContent + globals.Application.Config = configContent // - duration, err := time.ParseDuration(configContent.Spec.Synchronization.Time) - if err != nil { - globals.ExecContext.Logger.Fatalf(UnableParseDurationErrorMessage, err) - } + for { - // - processorObj, err := processor.NewProcessor() - if err != nil { - globals.ExecContext.Logger.Infof("error creating processor: %s", err.Error()) - } + // Create the processor to handle requests + processorObj, err := processor.NewProcessor() + if err != nil { + globals.Application.Logger.Infof("Failed to create a processor. Reason: ", err) + } - for { - globals.ExecContext.Logger.Info("syncing resources") - err = processorObj.SyncResources() + // Create the webserver to serve the requests + mux := http.NewServeMux() + mux.HandleFunc("/", processorObj.HandleRequest) + + // + webserverListenStr := configContent.Spec.Webserver.Listener.Host + ":" + + strconv.Itoa(configContent.Spec.Webserver.Listener.Port) + + globals.Application.Logger.Infof("Starting webserver on %s", webserverListenStr) + + err = http.ListenAndServe(webserverListenStr, mux) if err != nil { - globals.ExecContext.Logger.Infof("error syncing resources: %s", err) + globals.Application.Logger.Infof("Server failed. Reason: ", err) } - globals.ExecContext.Logger.Infof("syncing again in %s", duration.String()) - time.Sleep(duration) + globals.Application.Logger.Infof("Server will be restarted in some moments") + time.Sleep(5 * time.Second) } } diff --git a/internal/cmd/version/version.go b/internal/cmd/version/version.go index 24d0662..28f3dc3 100644 --- a/internal/cmd/version/version.go +++ b/internal/cmd/version/version.go @@ -10,7 +10,7 @@ import ( const ( descriptionShort = `Print the current version` descriptionLong = ` - Version show the current hitman version client.` + Version show the current bucket-simple-server version client.` ) func NewCommand() *cobra.Command { diff --git a/internal/config/config.go b/internal/config/config.go index 9ef05b0..bf72048 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,7 +3,7 @@ package config import ( "os" - "hitman/api/v1alpha1" + "bucket-simple-server/api/v1alpha1" "gopkg.in/yaml.v3" ) @@ -28,7 +28,11 @@ func ReadFile(filepath string) (config v1alpha1.ConfigT, err error) { return config, err } - config, err = Unmarshal(fileBytes) + // Expand environment variables present in the config + // This will cause expansion in the following way: field: "$FIELD" -> field: "value_of_field" + fileExpandedEnv := os.ExpandEnv(string(fileBytes)) + + config, err = Unmarshal([]byte(fileExpandedEnv)) return config, err } diff --git a/internal/globals/globals.go b/internal/globals/globals.go index fc19f6e..e56c622 100644 --- a/internal/globals/globals.go +++ b/internal/globals/globals.go @@ -1,8 +1,8 @@ package globals import ( + "bucket-simple-server/api/v1alpha1" "context" - "hitman/api/v1alpha1" "time" "go.uber.org/zap" @@ -10,13 +10,13 @@ import ( ) var ( - ExecContext = ExecutionContext{ + Application = ApplicationT{ Context: context.Background(), } ) // ExecutionContext TODO -type ExecutionContext struct { +type ApplicationT struct { Context context.Context Logger zap.SugaredLogger LogLevel string @@ -47,6 +47,6 @@ func SetLogger(logLevel string, disableTrace bool) (err error) { return err } - ExecContext.Logger = *logger.Sugar() + Application.Logger = *logger.Sugar() return nil } diff --git a/internal/kubernetes/kubernetes.go b/internal/kubernetes/kubernetes.go deleted file mode 100644 index f768ecf..0000000 --- a/internal/kubernetes/kubernetes.go +++ /dev/null @@ -1,26 +0,0 @@ -package kubernetes - -import ( - // Kubernetes clients - // Ref: https://pkg.go.dev/k8s.io/client-go/dynamic - dynamic "k8s.io/client-go/dynamic" - - // Ref: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client/config - ctrl "sigs.k8s.io/controller-runtime" -) - -// NewClient return a new Kubernetes client from client-go SDK -func NewClient() (client *dynamic.DynamicClient, err error) { - config, err := ctrl.GetConfig() - if err != nil { - return client, err - } - - // Create the clients to do requests to our friend: Kubernetes - client, err = dynamic.NewForConfig(config) - if err != nil { - return client, err - } - - return client, err -} diff --git a/internal/processor/processor.go b/internal/processor/processor.go index dbb8434..6112928 100644 --- a/internal/processor/processor.go +++ b/internal/processor/processor.go @@ -1,176 +1,128 @@ package processor import ( + "bucket-simple-server/api/v1alpha1" + "bucket-simple-server/internal/globals" "fmt" - "hitman/api/v1alpha1" - "hitman/internal/globals" - "hitman/internal/kubernetes" - "hitman/internal/template" - "reflect" + "io" + "net/http" "regexp" - "slices" + "strings" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/dynamic" + "cloud.google.com/go/storage" + "google.golang.org/api/option" ) type Processor struct { - Client *dynamic.DynamicClient -} - -func NewProcessor() (processor *Processor, err error) { - - client, err := kubernetes.NewClient() - if err != nil { - return processor, err - } + // compiledRouteList is a list of compiled regex expressions + // that represent the allowed routes + compiledRouteList []*regexp.Regexp - return &Processor{ - Client: client, - }, err + // GCSClient is a Google Cloud Storage client + GCSClient *storage.Client } // TODO -func (p *Processor) SyncResources() (err error) { +func NewProcessor() (*Processor, error) { - for _, configResource := range globals.ExecContext.Config.Spec.Resources { + newProcessor := Processor{} - // Matching a name is required - if reflect.ValueOf(configResource.Target.Name).IsZero() { - globals.ExecContext.Logger.Infof("target name or namespace selector is missing for group '%s' version '%s' resource '%s'. Skipping", - configResource.Target.Group, configResource.Target.Version, configResource.Target.Resource) - continue - } - - // Matching a name is required - if configResource.Target.Name.MatchExact != "" && configResource.Target.Name.MatchRegex != "" { - globals.ExecContext.Logger.Infof("target name can only have one selector: matchExact or matchRegex. Skipping") - continue - } - - if configResource.Target.Namespace.MatchExact != "" && configResource.Target.Namespace.MatchRegex != "" { - globals.ExecContext.Logger.Infof("targets namespace can only have one selector: matchExact or matchRegex. Skipping") - continue - } - - // Get the resources of the target type - gvr := schema.GroupVersionResource{ - Group: configResource.Target.Group, - Version: configResource.Target.Version, - Resource: configResource.Target.Resource, - } + // Compile routes just once to increase performance + ctrList, err := newProcessor.compileRouteExpressions(globals.Application.Config.Spec.Webserver.AllowedTargets) + if err != nil { + return &newProcessor, fmt.Errorf("error compiling allowed routes regex: %s", err) + } - resourceRaw := p.Client.Resource(gvr) + newProcessor.compiledRouteList = ctrList - if configResource.Target.Namespace.MatchExact != "" { - resourceRaw.Namespace(configResource.Target.Namespace.MatchExact) - } + // + newProcessor.GCSClient, err = storage.NewClient(globals.Application.Context, + option.WithCredentialsFile(globals.Application.Config.Spec.Source.GCS.Credentials.Path)) + if err != nil { + return &newProcessor, fmt.Errorf("error creating GCS client: %s", err) + } - resourceList, err := resourceRaw.List(globals.ExecContext.Context, v1.ListOptions{}) - if err != nil { - globals.ExecContext.Logger.Infof("error listing resources of type '%s' in namespace '%s': %s", - gvr.String(), configResource.Target.Namespace, err) - continue - } + return &newProcessor, err +} - // - compiledRegex, err := regexp.Compile(configResource.Target.Name.MatchRegex) - if err != nil { - globals.ExecContext.Logger.Infof("error compiling regular expression '%s' for resource name: %s", configResource.Target.Name.MatchRegex, err) - continue - } +// compileRouteExpressions return a list of compiled regex expressions of routes passed in allowed targets. +func (p *Processor) compileRouteExpressions(targets []v1alpha1.AllowedTargetT) (compiledRouteList []*regexp.Regexp, err error) { - compiledRegexNamespace, err := regexp.Compile(configResource.Target.Namespace.MatchRegex) + for _, target := range targets { + compiledRegex, err := regexp.Compile(target.Route) if err != nil { - globals.ExecContext.Logger.Infof("error compiling regular expression '%s' for resource namespace: %s", configResource.Target.Name.MatchRegex, err) - continue + return compiledRouteList, fmt.Errorf("error compiling regex %s: %s", target.Route, err) } - // Perform the actions over the resources - for _, resource := range resourceList.Items { - - // Matching namespace by regex and resource does NOT meet? Skip - if configResource.Target.Namespace.MatchRegex != "" && - !compiledRegexNamespace.MatchString(resource.GetNamespace()) { - continue - } - - // Matching name by exact string and resource does NOT meet? Skip - if configResource.Target.Name.MatchExact != "" && - resource.GetName() != configResource.Target.Name.MatchExact { - continue - } - - // Matching name by regex and resource does NOT meet? Skip - if configResource.Target.Name.MatchRegex != "" && - !compiledRegex.MatchString(resource.GetName()) { - continue - } - - // Process this object. Delete in case of success - objectDeleted, err := p.processObject(gvr, resource, configResource.Conditions) - if err != nil { - globals.ExecContext.Logger.Infof("error processing object: %s", err) - continue - } - - if !objectDeleted { - globals.ExecContext.Logger.Infof("resource '%s' in namespace '%s' did NOT meet the conditions", - resource.GetName(), resource.GetNamespace()) - continue - } - - globals.ExecContext.Logger.Infof("resource '%s' in namespace '%s' was deleted successfully", resource.GetName(), resource.GetNamespace()) - } + compiledRouteList = append(compiledRouteList, compiledRegex) } - return err + return compiledRouteList, nil } -// processObject process an object coming from arguments. -// It computes templating, evaluates conditions and decides whether to delete it or not. -func (p *Processor) processObject(gvr schema.GroupVersionResource, object unstructured.Unstructured, conditionList []v1alpha1.ConditionT) (result bool, err error) { +// TODO +func (p *Processor) HandleRequest(w http.ResponseWriter, r *http.Request) { - if globals.ExecContext.LogLevel == "debug" { - globals.ExecContext.Logger.Infof("processing object: group: '%s', version: '%s', resource: '%s', name: '%s', namespace: '%s'", - gvr.Group, gvr.Version, gvr.Resource, object.GetName(), object.GetNamespace()) + // Check Authorization header presence + authorizationHeader := r.Header.Get("Authorization") + if authorizationHeader == "" { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return } - // Create the object that will be injected on templating system - templateInjectedObject := map[string]interface{}{} - templateInjectedObject["object"] = object.Object + // Check Authorization header format + authorizationHeaderParts := strings.Split(authorizationHeader, " ") + if len(authorizationHeaderParts) != 2 { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } - // Evaluate the conditions for targeted object - var conditionFlags []bool + if authorizationHeaderParts[0] != "Bearer" { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } - for _, condition := range conditionList { + // Check Authorization header token + // ATM, only Bearer tokens are supported + requestAuthorized := false + for _, credential := range globals.Application.Config.Spec.Webserver.Credentials { - parsedKey, err := template.EvaluateTemplate(condition.Key, templateInjectedObject) - if err != nil { - return false, fmt.Errorf("error evaluating condition template: %s", err) + if strings.ToLower(credential.Type) != "bearer" { + continue } - conditionFlags = append(conditionFlags, parsedKey == condition.Value) + if credential.Token == authorizationHeaderParts[1] { + requestAuthorized = true + } + } + + if !requestAuthorized { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } - if globals.ExecContext.LogLevel == "debug" { - globals.ExecContext.Logger.Infof("condition: key: '%s', value: '%s', equals: '%t'", - parsedKey, condition.Value, parsedKey == condition.Value) + // Check if the route is allowed + urlPathAllowed := false + for _, compiledRoute := range p.compiledRouteList { + if compiledRoute.MatchString(r.URL.Path) { + urlPathAllowed = true } } - // Conditions not met. Skip - if slices.Contains(conditionFlags, false) { - return false, err + if !urlPathAllowed { + http.Error(w, "Forbidden", http.StatusForbidden) + return } - // Finally, delete the object - err = p.Client.Resource(gvr).Namespace(object.GetNamespace()). - Delete(globals.ExecContext.Context, object.GetName(), v1.DeleteOptions{}) + // Get the GCS file reader + objectPath := strings.TrimPrefix(r.URL.Path, "/") + srcReader, err := p.GCSClient.Bucket(globals.Application.Config.Spec.Source.GCS.Bucket).Object(objectPath).NewReader(globals.Application.Context) if err != nil { - return false, fmt.Errorf("error deleting object: %s", err) + globals.Application.Logger.Infof("Error reading file from GCS: ", err) + http.Error(w, "Not Found", http.StatusNotFound) + return } + defer srcReader.Close() - return true, err + io.Copy(w, srcReader) } diff --git a/internal/template/functions.go b/internal/template/functions.go deleted file mode 100644 index 8a3bbf5..0000000 --- a/internal/template/functions.go +++ /dev/null @@ -1,165 +0,0 @@ -package template - -import ( - "bytes" - "encoding/json" - "strings" - "text/template" - - "github.com/BurntSushi/toml" - "github.com/Masterminds/sprig" - "sigs.k8s.io/yaml" -) - -// FOLKS, ATTENTION HERE: -// Some parts of the magic you are going to see are replicated from Helm templating engine. -// We decided to use Golang templating and add, more or less, the same extra functionality to this operator -// for people who are already comfortable with Helm. Not all the extra functionality was added to keep this simpler. -// Ref: https://github.com/helm/helm/blob/main/pkg/engine/funcs.go - -func EvaluateTemplate(templateString string, data map[string]interface{}) (result string, err error) { - templateFunctionsMap := GetFunctionsMap() - - // Create a Template object from the given string - parsedTemplate, err := template.New("main").Funcs(templateFunctionsMap).Parse(templateString) - if err != nil { - return result, err - } - - // Create a new buffer to store the templating result - buffer := new(bytes.Buffer) - - err = parsedTemplate.Execute(buffer, data) - if err != nil { - return result, err - } - - return buffer.String(), nil -} - -// GetFunctionsMap return a map with equivalency between functions for inside templating and real Golang ones -func GetFunctionsMap() template.FuncMap { - f := sprig.TxtFuncMap() - - // Delete risky functions - // Ref: http://masterminds.github.io/sprig/os.html - delete(f, "env") - delete(f, "expandenv") - - // Add some extra functionality - extra := template.FuncMap{ - "toToml": toTOML, - "toYaml": toYAML, - "fromYaml": fromYAML, - "fromYamlArray": fromYAMLArray, - "toJson": toJSON, - "fromJson": fromJSON, - "fromJsonArray": fromJSONArray, - } - - for k, v := range extra { - f[k] = v - } - - return f -} - -// toYAML takes an interface, marshals it to yaml, and returns a string. It will -// always return a string, even on marshal error (empty string). -// -// This is designed to be called from a template. -func toYAML(v interface{}) string { - data, err := yaml.Marshal(v) - if err != nil { - // Swallow errors inside of a template. - return "" - } - return strings.TrimSuffix(string(data), "\n") -} - -// fromYAML converts a YAML document into a map[string]interface{}. -// -// This is not a general-purpose YAML parser, and will not parse all valid -// YAML documents. Additionally, because its intended use is within templates -// it tolerates errors. It will insert the returned error message string into -// m["Error"] in the returned map. -func fromYAML(str string) map[string]interface{} { - m := map[string]interface{}{} - - if err := yaml.Unmarshal([]byte(str), &m); err != nil { - m["Error"] = err.Error() - } - return m -} - -// fromYAMLArray converts a YAML array into a []interface{}. -// -// This is not a general-purpose YAML parser, and will not parse all valid -// YAML documents. Additionally, because its intended use is within templates -// it tolerates errors. It will insert the returned error message string as -// the first and only item in the returned array. -func fromYAMLArray(str string) []interface{} { - a := []interface{}{} - - if err := yaml.Unmarshal([]byte(str), &a); err != nil { - a = []interface{}{err.Error()} - } - return a -} - -// toTOML takes an interface, marshals it to toml, and returns a string. It will -// always return a string, even on marshal error (empty string). -// -// This is designed to be called from a template. -func toTOML(v interface{}) string { - b := bytes.NewBuffer(nil) - e := toml.NewEncoder(b) - err := e.Encode(v) - if err != nil { - return err.Error() - } - return b.String() -} - -// toJSON takes an interface, marshals it to json, and returns a string. It will -// always return a string, even on marshal error (empty string). -// -// This is designed to be called from a template. -func toJSON(v interface{}) string { - data, err := json.Marshal(v) - if err != nil { - // Swallow errors inside of a template. - return "" - } - return string(data) -} - -// fromJSON converts a JSON document into a map[string]interface{}. -// -// This is not a general-purpose JSON parser, and will not parse all valid -// JSON documents. Additionally, because its intended use is within templates -// it tolerates errors. It will insert the returned error message string into -// m["Error"] in the returned map. -func fromJSON(str string) map[string]interface{} { - m := make(map[string]interface{}) - - if err := json.Unmarshal([]byte(str), &m); err != nil { - m["Error"] = err.Error() - } - return m -} - -// fromJSONArray converts a JSON array into a []interface{}. -// -// This is not a general-purpose JSON parser, and will not parse all valid -// JSON documents. Additionally, because its intended use is within templates -// it tolerates errors. It will insert the returned error message string as -// the first and only item in the returned array. -func fromJSONArray(str string) []interface{} { - a := []interface{}{} - - if err := json.Unmarshal([]byte(str), &a); err != nil { - a = []interface{}{err.Error()} - } - return a -}