Merge remote-tracking branch 'origin/feature/kube-crd-control'
This commit is contained in:
commit
a3a806a54f
@ -4,7 +4,7 @@ tmp_dir = "tmp"
|
||||
|
||||
[build]
|
||||
args_bin = []
|
||||
bin = "./tmp/main"
|
||||
bin = ";set -o allexport && source ./.env && set +o allexport; ./tmp/main"
|
||||
cmd = "go build -o ./tmp/main ./cmd/operator"
|
||||
delay = 1000
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||
|
||||
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@ -0,0 +1,5 @@
|
||||
Tiltfile
|
||||
Dockerfile
|
||||
.env.example
|
||||
.git
|
||||
.gitignore
|
||||
2
.env.example
Normal file
2
.env.example
Normal file
@ -0,0 +1,2 @@
|
||||
FLINK_API_URL=127.0.0.1:8081
|
||||
SAVEPOINT_PATH=/opt/flink/savepoints
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
db
|
||||
*.log
|
||||
tmp
|
||||
*.jar
|
||||
*.jar
|
||||
.env
|
||||
20
.vscode/launch.json
vendored
Normal file
20
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"env": {
|
||||
"FLINK_API_URL": "127.0.0.1:8081",
|
||||
"SAVEPOINT_PATH": "/opt/flink/savepoints"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/cmd/operator"
|
||||
}
|
||||
]
|
||||
}
|
||||
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@ -1,5 +1,19 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"flink"
|
||||
"apiextensions",
|
||||
"clientcmd",
|
||||
"controllerutil",
|
||||
"deepcopy",
|
||||
"Finalizer",
|
||||
"flink",
|
||||
"gitea",
|
||||
"gonanoid",
|
||||
"logicamp",
|
||||
"Namespaceable",
|
||||
"nindent",
|
||||
"reactivex",
|
||||
"repsert",
|
||||
"rxgo",
|
||||
"tolerations"
|
||||
]
|
||||
}
|
||||
34
Dockerfile
Normal file
34
Dockerfile
Normal file
@ -0,0 +1,34 @@
|
||||
FROM public.ecr.aws/docker/library/golang:1.23.4-bookworm AS build
|
||||
|
||||
ARG upx_version=4.2.4
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends xz-utils && \
|
||||
curl -Ls https://github.com/upx/upx/releases/download/v${upx_version}/upx-${upx_version}-amd64_linux.tar.xz -o - | tar xvJf - -C /tmp && \
|
||||
cp /tmp/upx-${upx_version}-amd64_linux/upx /usr/local/bin/ && \
|
||||
chmod +x /usr/local/bin/upx && \
|
||||
apt-get remove -y xz-utils && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set destination for COPY
|
||||
WORKDIR /app
|
||||
|
||||
# Download Go modules
|
||||
COPY go.mod go.sum ./
|
||||
RUN --mount=type=cache,target="/go" go mod download -x
|
||||
|
||||
COPY . .
|
||||
|
||||
# Build
|
||||
ENV GOCACHE=/root/.cache/go-build
|
||||
RUN --mount=type=cache,target="/go" --mount=type=cache,target="/root/.cache/go-build" CGO_ENABLED=1 GOOS=linux go build -ldflags '-s -w' -o /flink-kube-operator ./cmd/operator
|
||||
RUN upx -q -5 /flink-kube-operator
|
||||
|
||||
FROM public.ecr.aws/docker/library/busybox:1.37.0 AS final
|
||||
|
||||
|
||||
COPY --from=build /flink-kube-operator /flink-kube-operator
|
||||
|
||||
EXPOSE 8083
|
||||
|
||||
# Run
|
||||
CMD ["/flink-kube-operator"]
|
||||
22
Dockerfile.flink
Normal file
22
Dockerfile.flink
Normal file
@ -0,0 +1,22 @@
|
||||
FROM public.ecr.aws/docker/library/flink:1.20.0-scala_2.12-java17
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /opt/flink
|
||||
|
||||
# Set environment variables for Flink mini-cluster
|
||||
ENV FLINK_HOME /opt/flink
|
||||
ENV PATH=$FLINK_HOME/bin:$PATH
|
||||
|
||||
# Expose necessary ports for the Flink UI (JobManager) and job manager
|
||||
EXPOSE 8081 6123
|
||||
|
||||
COPY ./start-cluster.sh /opt/flink/bin/start-cluster.sh
|
||||
RUN chmod +x /opt/flink/bin/start-cluster.sh
|
||||
|
||||
RUN wget -q https://repo1.maven.org/maven2/org/apache/flink/flink-connector-kafka/3.4.0-1.20/flink-connector-kafka-3.4.0-1.20.jar -P /opt/flink/lib/
|
||||
RUN wget -q https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/3.9.0/kafka-clients-3.9.0.jar -P /opt/flink/lib/
|
||||
RUN wget -q https://repo1.maven.org/maven2/org/apache/flink/flink-avro/1.20.0/flink-avro-1.20.0.jar -P /opt/flink/lib/
|
||||
RUN wget -q https://repo1.maven.org/maven2/org/apache/flink/flink-avro-confluent-registry/1.20.0/flink-avro-confluent-registry-1.20.0.jar -P /opt/flink/lib/
|
||||
|
||||
# Command to start Flink JobManager and TaskManager in a mini-cluster setup
|
||||
CMD ["bin/start-cluster.sh"]
|
||||
108
Tiltfile
Normal file
108
Tiltfile
Normal file
@ -0,0 +1,108 @@
|
||||
# Welcome to Tilt!
|
||||
# To get you started as quickly as possible, we have created a
|
||||
# starter Tiltfile for you.
|
||||
#
|
||||
# Uncomment, modify, and delete any commands as needed for your
|
||||
# project's configuration.
|
||||
|
||||
|
||||
# Output diagnostic messages
|
||||
# You can print log messages, warnings, and fatal errors, which will
|
||||
# appear in the (Tiltfile) resource in the web UI. Tiltfiles support
|
||||
# multiline strings and common string operations such as formatting.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.warn
|
||||
print("""
|
||||
-----------------------------------------------------------------
|
||||
✨ Hello Tilt! This appears in the (Tiltfile) pane whenever Tilt
|
||||
evaluates this file.
|
||||
-----------------------------------------------------------------
|
||||
""".strip())
|
||||
warn('ℹ️ Open {tiltfile_path} in your favorite editor to get started.'.format(
|
||||
tiltfile_path=config.main_path))
|
||||
|
||||
|
||||
# Build Docker image
|
||||
# Tilt will automatically associate image builds with the resource(s)
|
||||
# that reference them (e.g. via Kubernetes or Docker Compose YAML).
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.docker_build
|
||||
#
|
||||
docker_build('lcr.logicamp.tech/library/flink-kube-operator:latest',
|
||||
context='.',
|
||||
# (Optional) Use a custom Dockerfile path
|
||||
dockerfile='Dockerfile',
|
||||
# (Optional) Filter the paths used in the build
|
||||
# only=['./tmp/main'],
|
||||
# (Recommended) Updating a running container in-place
|
||||
# https://docs.tilt.dev/live_update_reference.html
|
||||
# live_update=[
|
||||
# # Sync files from host to container
|
||||
# sync('./tmp/main', '/flink-kube-operator'),
|
||||
# #sync('./app', '/src/'),
|
||||
# # Execute commands inside the container when certain
|
||||
# # paths change
|
||||
# #run('/src/codegen.sh', trigger=['./app/api'])
|
||||
# run('/flink-kube-operator', trigger=["/flink-kube-operator"])
|
||||
# ]
|
||||
)
|
||||
|
||||
|
||||
# Apply Kubernetes manifests
|
||||
# Tilt will build & push any necessary images, re-deploying your
|
||||
# resources as they change.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.k8s_yaml
|
||||
#
|
||||
# k8s_yaml(['k8s/deployment.yaml', 'k8s/service.yaml'])
|
||||
|
||||
|
||||
# Customize a Kubernetes resource
|
||||
# By default, Kubernetes resource names are automatically assigned
|
||||
# based on objects in the YAML manifests, e.g. Deployment name.
|
||||
#
|
||||
# Tilt strives for sane defaults, so calling k8s_resource is
|
||||
# optional, and you only need to pass the arguments you want to
|
||||
# override.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/api.html#api.k8s_resource
|
||||
#
|
||||
# k8s_resource('my-deployment',
|
||||
# # map one or more local ports to ports on your Pod
|
||||
# port_forwards=['5000:8080'],
|
||||
# # change whether the resource is started by default
|
||||
# auto_init=False,
|
||||
# # control whether the resource automatically updates
|
||||
# trigger_mode=TRIGGER_MODE_MANUAL
|
||||
# )
|
||||
|
||||
# local_resource('build', cmd='go build -o ./tmp/main -ldflags \'-s -w\' ./cmd/operator && upx -q -5 ./tmp/main')
|
||||
# Run local commands
|
||||
# Local commands can be helpful for one-time tasks like installing
|
||||
# project prerequisites. They can also manage long-lived processes
|
||||
# for non-containerized services or dependencies.
|
||||
#
|
||||
# More info: https://docs.tilt.dev/local_resource.html
|
||||
#
|
||||
# local_resource('install-helm',
|
||||
# cmd='which helm > /dev/null || brew install helm',
|
||||
# # `cmd_bat`, when present, is used instead of `cmd` on Windows.
|
||||
# cmd_bat=[
|
||||
# 'powershell.exe',
|
||||
# '-Noninteractive',
|
||||
# '-Command',
|
||||
# '& {if (!(Get-Command helm -ErrorAction SilentlyContinue)) {scoop install helm}}'
|
||||
# ]
|
||||
# )
|
||||
|
||||
|
||||
# Extensions are open-source, pre-packaged functions that extend Tilt
|
||||
#
|
||||
# More info: https://github.com/tilt-dev/tilt-extensions
|
||||
#
|
||||
load('ext://git_resource', 'git_checkout')
|
||||
|
||||
|
||||
k8s_yaml(helm('./helm', name="flink-operator", namespace='logiline'))
|
||||
allow_k8s_contexts('logicamp-staging-admin@logicamp-staging')
|
||||
|
||||
@ -1,28 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/config"
|
||||
"flink-kube-operator/internal/managed_job"
|
||||
"fmt"
|
||||
"flink-kube-operator/internal/crd"
|
||||
"flink-kube-operator/internal/manager"
|
||||
"flink-kube-operator/pkg"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gitea.com/logicamp/lc"
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
lc.Logger.Debug("start")
|
||||
|
||||
db, err := badger.Open(badger.DefaultOptions("./db"))
|
||||
if err != nil {
|
||||
lc.Logger.Fatal("[main] error on open db", zap.Error(err))
|
||||
}
|
||||
defer db.Close()
|
||||
// init kubernetes flink job crd watch
|
||||
crdInstance := crd.New()
|
||||
|
||||
c, err := api.New("127.0.0.1:8081")
|
||||
// create flink api instance
|
||||
c, err := api.New(os.Getenv("FLINK_API_URL"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -32,36 +27,26 @@ func main() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(clusterConfig)
|
||||
pkg.Logger.Info("[main]", zap.Any("cluster-config", clusterConfig))
|
||||
|
||||
jars, err := c.Jars()
|
||||
if err != nil {
|
||||
lc.Logger.Error("error on getting jars", zap.Error(err))
|
||||
}
|
||||
lc.Logger.Debug("[main] jars", zap.Any("jars", jars))
|
||||
// init flink job manager
|
||||
manager.NewManager(c, crdInstance)
|
||||
|
||||
jobs, err := c.Jobs()
|
||||
if err != nil {
|
||||
lc.Logger.Error("error on getting jars", zap.Error(err))
|
||||
}
|
||||
lc.Logger.Debug("[main] jobs", zap.Any("jobs", jobs))
|
||||
// for _, jobDef := range config.Jobs {
|
||||
// managed_job.NewManagedJob(c, db, jobDef)
|
||||
// }
|
||||
|
||||
config := lc.LoadYamlConfig[config.Config]("./config.yaml")
|
||||
for _, jobDef := range config.Jobs {
|
||||
managed_job.NewManagedJob(c, db, jobDef)
|
||||
}
|
||||
|
||||
for _, job := range jobs.Jobs {
|
||||
job, err := c.Job(job.ID)
|
||||
if err != nil {
|
||||
lc.Logger.Error("error getting job info", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
if job.State == "RUNNING" {
|
||||
lc.Logger.Debug("[main] running job", zap.String("jobId", job.ID))
|
||||
}
|
||||
// lc.Logger.Debug("[main]", zap.Any("job", job))
|
||||
}
|
||||
// for _, job := range jobs.Jobs {
|
||||
// job, err := c.Job(job.ID)
|
||||
// if err != nil {
|
||||
// pkg.Logger.Error("error getting job info", zap.Error(err))
|
||||
// continue
|
||||
// }
|
||||
// if job.State == "RUNNING" {
|
||||
// pkg.Logger.Debug("[main] running job", zap.String("jobId", job.ID))
|
||||
// }
|
||||
// // pkg.Logger.Debug("[main]", zap.Any("job", job))
|
||||
// }
|
||||
|
||||
cancelChan := make(chan os.Signal, 1)
|
||||
sig := <-cancelChan
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
jobs:
|
||||
- key: price-processor
|
||||
name: Price Processor
|
||||
entryClass: top.bazargam.Main
|
||||
jarURI: http://price-processor.bz2/price-processor-v0.0.1.jar
|
||||
savepointInterval: 3m
|
||||
115
crds.yaml
Normal file
115
crds.yaml
Normal file
@ -0,0 +1,115 @@
|
||||
# flink-crd.yaml
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: flink-jobs.flink.logicamp.tech
|
||||
spec:
|
||||
group: flink.logicamp.tech
|
||||
names:
|
||||
kind: FlinkJob
|
||||
plural: flink-jobs
|
||||
singular: flink-job
|
||||
shortNames:
|
||||
- lfj
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
required:
|
||||
- key
|
||||
- jarUri
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
entryClass:
|
||||
type: string
|
||||
parallelism:
|
||||
type: integer
|
||||
jarUri:
|
||||
type: string
|
||||
savepointInterval:
|
||||
type: string
|
||||
format: duration
|
||||
flinkConfiguration:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
resources:
|
||||
type: object
|
||||
properties:
|
||||
requests:
|
||||
type: object
|
||||
properties:
|
||||
memory:
|
||||
type: string
|
||||
cpu:
|
||||
type: string
|
||||
limits:
|
||||
type: object
|
||||
properties:
|
||||
memory:
|
||||
type: string
|
||||
cpu:
|
||||
type: string
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
jobStatus:
|
||||
type: string
|
||||
startTime:
|
||||
type: string
|
||||
jobId:
|
||||
type: string
|
||||
jarId:
|
||||
type: string
|
||||
error:
|
||||
type: string
|
||||
lastSavepointPath:
|
||||
type: string
|
||||
lifeCycleStatus:
|
||||
type: string
|
||||
savepointTriggerId:
|
||||
type: string
|
||||
lastSavepointDate:
|
||||
type: string
|
||||
format: time
|
||||
lastRestoredSavepointDate:
|
||||
type: string
|
||||
format: time
|
||||
lastRestoredSavepointRestoredDate:
|
||||
type: string
|
||||
format: time
|
||||
runningJarURI:
|
||||
type: string
|
||||
pauseSavepointTriggerId:
|
||||
type: string
|
||||
restoredCount:
|
||||
type: number
|
||||
additionalPrinterColumns:
|
||||
- name: Status
|
||||
type: string
|
||||
jsonPath: .status.jobStatus
|
||||
- name: Age
|
||||
type: date
|
||||
jsonPath: .metadata.creationTimestamp
|
||||
- name: Life Cycle Status
|
||||
type: string
|
||||
jsonPath: .status.lifeCycleStatus
|
||||
- name: Last Savepoint
|
||||
type: date
|
||||
jsonPath: .status.lastSavepointDate
|
||||
- name: Last Restored Savepoint
|
||||
type: date
|
||||
jsonPath: .status.lastRestoredSavepointDate
|
||||
- name: Restored Count
|
||||
type: number
|
||||
jsonPath: .status.restoredCount
|
||||
15
example-job.yaml
Normal file
15
example-job.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
# flink-job-instance.yaml
|
||||
apiVersion: flink.logicamp.tech/v1alpha1
|
||||
kind: FlinkJob
|
||||
metadata:
|
||||
name: my-flink-job
|
||||
namespace: default
|
||||
spec:
|
||||
key: word-count
|
||||
name: "Word Count Example"
|
||||
entryClass: "org.apache.flink.examples.java.wordcount.WordCount"
|
||||
parallelism: 2
|
||||
jarUri: "http://192.168.7.7:8080/product-enrichment-processor.jar"
|
||||
flinkConfiguration:
|
||||
taskmanager.numberOfTaskSlots: "2"
|
||||
parallelism.default: "2"
|
||||
111
go.mod
111
go.mod
@ -3,50 +3,69 @@ module flink-kube-operator
|
||||
go 1.23.2
|
||||
|
||||
require (
|
||||
gitea.com/logicamp/lc v1.14.6 // indirect
|
||||
github.com/IBM/sarama v1.43.3 // indirect
|
||||
github.com/arangodb/go-driver v1.6.4 // indirect
|
||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/confluentinc/confluent-kafka-go/v2 v2.6.0 // indirect
|
||||
github.com/danielgtaylor/huma/v2 v2.26.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgraph-io/badger/v4 v4.5.0 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.0.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/eapache/go-resiliency v1.7.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/flatbuffers v24.3.25+incompatible // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
|
||||
github.com/jcmturner/gofork v1.7.6 // indirect
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/logi-camp/go-flink-client v0.1.0 // indirect
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/nats-io/nats.go v1.37.0 // indirect
|
||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
github.com/logi-camp/go-flink-client v0.2.0
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0
|
||||
github.com/samber/lo v1.47.0
|
||||
go.uber.org/zap v1.27.0
|
||||
k8s.io/apimachinery v0.31.3
|
||||
k8s.io/client-go v0.31.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 // 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/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
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.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/reactivex/rxgo/v2 v2.5.0
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/teivah/onecontext v0.0.0-20200513185103-40f981bfd775 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/oauth2 v0.21.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/term v0.26.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/api v0.31.3 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241127205056-99599406b04f // indirect
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.19.2
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.3 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
322
go.sum
322
go.sum
@ -1,99 +1,69 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
gitea.com/logicamp/lc v1.14.6 h1:jgtrYwbqvWU/cxT9mDFCToK7D+tEpGyhV3FnSn3hKBw=
|
||||
gitea.com/logicamp/lc v1.14.6/go.mod h1:P29QjvOVa1VnEZIFi+Mab7uRbO/qRrbZPdARSpi4qXs=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/IBM/sarama v1.43.3 h1:Yj6L2IaNvb2mRBop39N7mmJAHBVY3dTPncr3qGVkxPA=
|
||||
github.com/IBM/sarama v1.43.3/go.mod h1:FVIRaLrhK3Cla/9FfRF5X9Zua2KpS3SYIXxhac1H+FQ=
|
||||
github.com/arangodb/go-driver v1.6.4 h1:tuizDP620e3OFaoFkEh07n4bHSTvCOvm5qVGQ/+zMrs=
|
||||
github.com/arangodb/go-driver v1.6.4/go.mod h1:oLZCzkEGh82I2XBcMkrDtqsMXFg6QkIRgbqLGalh6jc=
|
||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2LcQBbxd0ZFdbGSyRKTYMZCfBbw/pMJFOk1g=
|
||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
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/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/confluentinc/confluent-kafka-go/v2 v2.6.0 h1:VKnMT71Tl0dCp3lfGBp2D8eqQwc+amoDY5EeUgFHDDE=
|
||||
github.com/confluentinc/confluent-kafka-go/v2 v2.6.0/go.mod h1:hScqtFIGUI1wqHIgM3mjoqEou4VweGGGX7dMpcUKves=
|
||||
github.com/danielgtaylor/huma/v2 v2.26.0 h1:lON4pIcckuSQJNDi6WkOu0sS7mxvlNkTAGbc3BrRXTc=
|
||||
github.com/danielgtaylor/huma/v2 v2.26.0/go.mod h1:NbSFXRoOMh3BVmiLJQ9EbUpnPas7D9BeOxF/pZBAGa0=
|
||||
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
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/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/dgraph-io/badger/v4 v4.5.0 h1:TeJE3I1pIWLBjYhIYCA1+uxrjWEoJXImFBMEBVSm16g=
|
||||
github.com/dgraph-io/badger/v4 v4.5.0/go.mod h1:ysgYmIeG8dS/E8kwxT7xHyc7MkmwNYLRoYnFbr7387A=
|
||||
github.com/dgraph-io/ristretto/v2 v2.0.0 h1:l0yiSOtlJvc0otkqyMaDNysg8E9/F/TYZwMbxscNOAQ=
|
||||
github.com/dgraph-io/ristretto/v2 v2.0.0/go.mod h1:FVFokF2dRqXyPyeMnK1YDy8Fc6aTe0IKgbcd03CYeEk=
|
||||
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/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=
|
||||
github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
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/flink-go/api v0.0.1 h1:YK3TBZLV4TivPhjJ+Z316b2mSg72sPy3IOcm21OyaO4=
|
||||
github.com/flink-go/api v0.0.1/go.mod h1:nzM6X8dmpVRe3jqfQ4y05JeTIRWZPD4iT6kyEaFBG9A=
|
||||
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/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
|
||||
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
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-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
|
||||
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/logi-camp/go-flink-client v0.0.1 h1:VZI5ctoJEArwtBprIXZNk+cv5fEQZ4EcuKAbOY8Emvw=
|
||||
github.com/logi-camp/go-flink-client v0.0.1/go.mod h1:A79abedX6wGQI0FoICdZI7SRoGHj15QwMwWowgsKYFI=
|
||||
github.com/logi-camp/go-flink-client v0.0.3 h1:NT9FYJG7jqroq44jfJfRnva3NO/jgpgURcU0mFysK1A=
|
||||
github.com/logi-camp/go-flink-client v0.0.3/go.mod h1:A79abedX6wGQI0FoICdZI7SRoGHj15QwMwWowgsKYFI=
|
||||
github.com/logi-camp/go-flink-client v0.1.0 h1:uzBV6RGkyzZVdSQ8zAlUGbJ5hdXRspaPjzzYJUQ2aJU=
|
||||
github.com/logi-camp/go-flink-client v0.1.0/go.mod h1:A79abedX6wGQI0FoICdZI7SRoGHj15QwMwWowgsKYFI=
|
||||
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/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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
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/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/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-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/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
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.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||
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=
|
||||
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/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
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/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
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/logi-camp/go-flink-client v0.2.0 h1:PIyfJq7FjW28bnvemReCicIuQD7JzVgJDk2xPTZUS2s=
|
||||
github.com/logi-camp/go-flink-client v0.2.0/go.mod h1:A79abedX6wGQI0FoICdZI7SRoGHj15QwMwWowgsKYFI=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE=
|
||||
github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@ -101,121 +71,139 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
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/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
|
||||
github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/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.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
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/reactivex/rxgo/v2 v2.5.0 h1:FhPgHwX9vKdNQB2gq9EPt+EKk9QrrzoeztGbEEnZam4=
|
||||
github.com/reactivex/rxgo/v2 v2.5.0/go.mod h1:bs4fVZxcb5ZckLIOeIeVH942yunJLWDABWGbrHAW+qU=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
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/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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
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/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=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/teivah/onecontext v0.0.0-20200513185103-40f981bfd775 h1:BLNsFR8l/hj/oGjnJXkd4Vi3s4kQD3/3x8HSAE4bzN0=
|
||||
github.com/teivah/onecontext v0.0.0-20200513185103-40f981bfd775/go.mod h1:XUZ4x3oGhWfiOnUvTslnKKs39AWUct3g3yJvXTQSJOQ=
|
||||
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/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
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.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
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.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
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.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/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/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/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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
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.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
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.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
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/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-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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
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.0.0-20220811171246-fbc7d0a398ab/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.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.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-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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.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.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
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=
|
||||
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=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-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.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.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/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v2 v2.2.2/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/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8=
|
||||
k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
|
||||
k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
|
||||
k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
|
||||
k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4=
|
||||
k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4=
|
||||
k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs=
|
||||
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-20241127205056-99599406b04f h1:nLHvOvs1CZ+FAEwR4EqLeRLfbtWQNlIu5g393Hq/1UM=
|
||||
k8s.io/kube-openapi v0.0.0-20241127205056-99599406b04f/go.mod h1:iZjdMQzunI7O/sUrf/5WRX1gvaAIam32lKx9+paoLbU=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno=
|
||||
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.19.2 h1:3sPrF58XQEPzbE8T81TN6selQIMGbtYwuaJ6eDssDF8=
|
||||
sigs.k8s.io/controller-runtime v0.19.2/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.3 h1:sCP7Vv3xx/CWIuTPVN38lUPx0uw0lcLfzaiDa8Ja01A=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.3/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
||||
23
helm/.helmignore
Normal file
23
helm/.helmignore
Normal file
@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
24
helm/Chart.yaml
Normal file
24
helm/Chart.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
apiVersion: v2
|
||||
name: flink-kube-operator
|
||||
description: A Helm chart for Kubernetes
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "1.16.0"
|
||||
22
helm/templates/NOTES.txt
Normal file
22
helm/templates/NOTES.txt
Normal file
@ -0,0 +1,22 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "flink-kube-operator.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "flink-kube-operator.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "flink-kube-operator.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "flink-kube-operator.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||
{{- end }}
|
||||
62
helm/templates/_helpers.tpl
Normal file
62
helm/templates/_helpers.tpl
Normal file
@ -0,0 +1,62 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "flink-kube-operator.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
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 "flink-kube-operator.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "flink-kube-operator.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "flink-kube-operator.labels" -}}
|
||||
helm.sh/chart: {{ include "flink-kube-operator.chart" . }}
|
||||
{{ include "flink-kube-operator.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "flink-kube-operator.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "flink-kube-operator.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "flink-kube-operator.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "flink-kube-operator.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
71
helm/templates/flink/deploy.yaml
Normal file
71
helm/templates/flink/deploy.yaml
Normal file
@ -0,0 +1,71 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-flink # Adding the flink prefix to the name
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ .Release.Name }}-flink # Adding the flink prefix to the labels
|
||||
app.kubernetes.io/instance: {{ .Release.Name }} # Using the release name for instance
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ .Release.Name }}-flink # Adding the flink prefix to the selector
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ .Release.Name }}-flink # Adding the flink prefix to the template labels
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
spec:
|
||||
serviceAccountName: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
|
||||
containers:
|
||||
- name: flink
|
||||
image: {{ .Values.flink.image.repository }}:{{ .Values.flink.image.tag }}
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8081 # JobManager Web UI port
|
||||
- containerPort: 6121 # TaskManager communication port
|
||||
- containerPort: 6122 # TaskManager communication port
|
||||
env:
|
||||
- name: JOB_MANAGER_RPC_ADDRESS
|
||||
value: "localhost" # JobManager and TaskManager in the same container
|
||||
- name: FLINK_PROPERTIES
|
||||
value: |
|
||||
jobmanager.rpc.address: localhost
|
||||
jobmanager.memory.process.size: 2048m
|
||||
taskmanager.memory.process.size: 2048m
|
||||
taskmanager.data.port: 6125
|
||||
taskmanager.numberOfTaskSlots: {{ .Values.flink.taskManager.numberOfTaskSlots }}
|
||||
parallelism.default: {{ .Values.flink.parallelism.default }}
|
||||
state.backend: {{ .Values.flink.state.backend }}
|
||||
state.savepoints.dir: {{ .Values.flink.state.savepoints.dir }}
|
||||
rest.port: 8081
|
||||
rootLogger.level = DEBUG
|
||||
rootLogger.appenderRef.console.ref = ConsoleAppender
|
||||
web.upload.dir: /opt/flink/data/web-upload
|
||||
state.checkpoints.dir: file:///tmp/flink-checkpoints
|
||||
high-availability.type: kubernetes
|
||||
high-availability.storageDir: file:///opt/flink/ha
|
||||
kubernetes.cluster-id: cluster-one
|
||||
kubernetes.namespace: {{ .Release.Namespace }}
|
||||
volumeMounts:
|
||||
- name: flink-data
|
||||
mountPath: /opt/flink/data
|
||||
subPath: data
|
||||
- name: flink-data
|
||||
mountPath: /opt/flink/web-upload
|
||||
subPath: web-upload
|
||||
- name: flink-savepoints
|
||||
mountPath: /opt/flink/savepoints
|
||||
- name: flink-savepoints
|
||||
mountPath: /opt/flink/ha
|
||||
subPath: ha
|
||||
|
||||
volumes:
|
||||
- name: flink-data
|
||||
emptyDir: {} # Temporary storage for internal data
|
||||
- name: flink-savepoints
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.flink.state.savepoints.pvcName }} # PVC for savepoints persistence
|
||||
10
helm/templates/flink/pvc.yaml
Normal file
10
helm/templates/flink/pvc.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ .Values.flink.state.savepoints.pvcName }} # Adding the flink prefix to PVC name
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.flink.persistence.size }} # Use size defined in values.yaml
|
||||
15
helm/templates/flink/service.yaml
Normal file
15
helm/templates/flink/service.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: flink # Adding the flink prefix to the service name
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ .Release.Name }}-flink # Adding the flink prefix to labels
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
spec:
|
||||
ports:
|
||||
- port: 8081
|
||||
targetPort: 8081
|
||||
selector:
|
||||
app.kubernetes.io/name: {{ .Release.Name }}-flink # Adding the flink prefix to selector
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
type: ClusterIP # Change to LoadBalancer if you want external access
|
||||
61
helm/templates/operator/deployment.yaml
Normal file
61
helm/templates/operator/deployment.yaml
Normal file
@ -0,0 +1,61 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.fullname" . }}
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "flink-kube-operator.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 8 }}
|
||||
{{- with .Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: FLINK_API_URL
|
||||
value: {{ .Values.config.flinkApiUrl }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
|
||||
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
32
helm/templates/operator/hpa.yaml
Normal file
32
helm/templates/operator/hpa.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.fullname" . }}
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "flink-kube-operator.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
43
helm/templates/operator/ingress.yaml
Normal file
43
helm/templates/operator/ingress.yaml
Normal file
@ -0,0 +1,43 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.fullname" . }}
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.ingress.className }}
|
||||
ingressClassName: {{ . }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- with .pathType }}
|
||||
pathType: {{ . }}
|
||||
{{- end }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "flink-kube-operator.fullname" $ }}
|
||||
port:
|
||||
number: {{ $.Values.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
50
helm/templates/operator/role.yaml
Normal file
50
helm/templates/operator/role.yaml
Normal file
@ -0,0 +1,50 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }} # Namespace where the role is created
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- flink.logicamp.tech # API group of the FlinkJob CRD
|
||||
resources:
|
||||
- flink-jobs # The plural name of your custom resource
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- create
|
||||
- update
|
||||
- delete
|
||||
- patch
|
||||
- watch
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps", "pods", "services"]
|
||||
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["statefulsets"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["persistentvolumeclaims"]
|
||||
verbs: ["get", "list", "create", "delete"]
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumes"]
|
||||
verbs: ["get", "list"]
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }} # Namespace where the RoleBinding is created
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }} # Ensure that the service account is in the same namespace
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
15
helm/templates/operator/service.yaml
Normal file
15
helm/templates/operator/service.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.fullname" . }}
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "flink-kube-operator.selectorLabels" . | nindent 4 }}
|
||||
13
helm/templates/operator/serviceaccount.yaml
Normal file
13
helm/templates/operator/serviceaccount.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "flink-kube-operator.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "flink-kube-operator.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
|
||||
{{- end }}
|
||||
138
helm/values.yaml
Normal file
138
helm/values.yaml
Normal file
@ -0,0 +1,138 @@
|
||||
# Default values for flink-kube-operator.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
|
||||
replicaCount: 1
|
||||
|
||||
# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/
|
||||
image:
|
||||
repository: lcr.logicamp.tech/library/flink-kube-operator
|
||||
# This sets the pull policy for images.
|
||||
pullPolicy: Always
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: latest
|
||||
|
||||
# This is for the secretes for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||
imagePullSecrets: []
|
||||
# This is to override the chart name.
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
#This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Automatically mount a ServiceAccount's API credentials?
|
||||
automount: true
|
||||
# Annotations to add to the service account
|
||||
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: ""
|
||||
|
||||
# This is for setting Kubernetes Annotations to a Pod.
|
||||
# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
|
||||
podAnnotations: {}
|
||||
# This is for setting Kubernetes Labels to a Pod.
|
||||
# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
podLabels: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/
|
||||
service:
|
||||
# This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
|
||||
type: ClusterIP
|
||||
# This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports
|
||||
port: 80
|
||||
|
||||
# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources: {}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
|
||||
#This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
config:
|
||||
flinkApiUrl: flink:8081
|
||||
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
# Global values for the Flink deployment
|
||||
flink:
|
||||
image:
|
||||
repository: lcr.logicamp.tech/library/flink
|
||||
tag: 1.20.0-scala_2.12-java17-minicluster
|
||||
|
||||
parallelism:
|
||||
default: 1 # Default parallelism for Flink jobs
|
||||
|
||||
state:
|
||||
backend: rocksdb # Use RocksDB for state backend
|
||||
savepoints:
|
||||
dir: "file:///opt/flink/savepoints" # Directory to store savepoints
|
||||
pvcName: flink-savepoints-pvc # PVC for savepoints persistence
|
||||
|
||||
taskManager:
|
||||
numberOfTaskSlots: 100 # Number of task slots for TaskManager
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi # PVC size for savepoints storage
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
@ -1,15 +1,6 @@
|
||||
package config
|
||||
|
||||
import "time"
|
||||
|
||||
type JobDef struct {
|
||||
Key string `yaml:"key"`
|
||||
Name string `yaml:"name"`
|
||||
EntryClass string `yaml:"entryClass"`
|
||||
JarURI string `yaml:"jarURI"`
|
||||
SavepointInterval time.Duration `yaml:"savepointInterval"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Jobs []JobDef `yaml:"jobs"`
|
||||
FlinkApiUrl string `yaml:"flinkApiUrl"`
|
||||
DatabasePath string `yaml:"databasePath"`
|
||||
}
|
||||
|
||||
74
internal/crd/client/client.go
Normal file
74
internal/crd/client/client.go
Normal file
@ -0,0 +1,74 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type FlinkJobInterface interface {
|
||||
List(opts metav1.ListOptions) (*v1alpha1.FlinkJobList, error)
|
||||
Get(name string, options metav1.GetOptions) (*v1alpha1.FlinkJob, error)
|
||||
Create(*v1alpha1.FlinkJob) (*v1alpha1.FlinkJob, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
// ...
|
||||
}
|
||||
|
||||
type FlinkJobClient struct {
|
||||
restClient rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
func (c *FlinkJobClient) List(opts metav1.ListOptions) (*v1alpha1.FlinkJobList, error) {
|
||||
result := v1alpha1.FlinkJobList{}
|
||||
err := c.restClient.
|
||||
Get().
|
||||
Namespace(c.ns).
|
||||
Resource("FlinkJobs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do(context.Background()).
|
||||
Into(&result)
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *FlinkJobClient) Get(name string, opts metav1.GetOptions) (*v1alpha1.FlinkJob, error) {
|
||||
result := v1alpha1.FlinkJob{}
|
||||
err := c.restClient.
|
||||
Get().
|
||||
Namespace(c.ns).
|
||||
Resource("FlinkJobs").
|
||||
Name(name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do(context.Background()).
|
||||
Into(&result)
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *FlinkJobClient) Create(FlinkJob *v1alpha1.FlinkJob) (*v1alpha1.FlinkJob, error) {
|
||||
result := v1alpha1.FlinkJob{}
|
||||
err := c.restClient.
|
||||
Post().
|
||||
Namespace(c.ns).
|
||||
Resource("FlinkJobs").
|
||||
Body(FlinkJob).
|
||||
Do(context.Background()).
|
||||
Into(&result)
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *FlinkJobClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.restClient.
|
||||
Get().
|
||||
Namespace(c.ns).
|
||||
Resource("FlinkJobs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch(context.Background())
|
||||
}
|
||||
33
internal/crd/convert.go
Normal file
33
internal/crd/convert.go
Normal file
@ -0,0 +1,33 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func convertToUnstructured(obj v1alpha1.FlinkJob) (*unstructured.Unstructured, error) {
|
||||
// Convert the structured object to an unstructured map
|
||||
unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert to unstructured: %v", err)
|
||||
}
|
||||
|
||||
// Create an Unstructured object from the map
|
||||
unstructuredObj := &unstructured.Unstructured{
|
||||
Object: unstructuredMap,
|
||||
}
|
||||
|
||||
return unstructuredObj, nil
|
||||
}
|
||||
|
||||
func convertFromUnstructured(in *unstructured.Unstructured) (*v1alpha1.FlinkJob, error) {
|
||||
job := &v1alpha1.FlinkJob{}
|
||||
err := runtime.DefaultUnstructuredConverter.FromUnstructured(in.Object, job)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return job, nil
|
||||
}
|
||||
14
internal/crd/finalizer.go
Normal file
14
internal/crd/finalizer.go
Normal file
@ -0,0 +1,14 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"github.com/reactivex/rxgo/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
)
|
||||
|
||||
func (crd Crd) manageFinalizer(jobEventObservable rxgo.Observable) {
|
||||
for j := range jobEventObservable.Observe() {
|
||||
jobEvent := j.V.(*FlinkJobCrdEvent)
|
||||
//pkg.Logger.Debug("[crd] [manage-finalizer] adding finalizer for", zap.String("name", jobEvent.Job.GetName()))
|
||||
controllerutil.AddFinalizer(jobEvent.Job, "")
|
||||
}
|
||||
}
|
||||
45
internal/crd/new.go
Normal file
45
internal/crd/new.go
Normal file
@ -0,0 +1,45 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
type Crd struct {
|
||||
client dynamic.NamespaceableResourceInterface
|
||||
}
|
||||
|
||||
func New() *Crd {
|
||||
// Get Kubernetes config
|
||||
config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
|
||||
if err != nil {
|
||||
config, err = rest.InClusterConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create dynamic client
|
||||
dynamicClient, err := dynamic.NewForConfig(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Get FlinkJob resource interface
|
||||
flinkJobClient := dynamicClient.Resource(v1alpha1.FlinkJobGVR)
|
||||
|
||||
crd := Crd{
|
||||
client: flinkJobClient,
|
||||
}
|
||||
|
||||
// Watch for FlinkJob creation
|
||||
jobEventObservable := crd.watchFlinkJobs()
|
||||
|
||||
// add finalizer to new resources
|
||||
go crd.manageFinalizer(jobEventObservable)
|
||||
|
||||
return &crd
|
||||
}
|
||||
62
internal/crd/patch.go
Normal file
62
internal/crd/patch.go
Normal file
@ -0,0 +1,62 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"go.uber.org/zap"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
func (crd *Crd) Patch(jobUid types.UID, patchData map[string]interface{}) error {
|
||||
job := GetJob(jobUid)
|
||||
|
||||
patchBytes, err := json.Marshal(patchData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error marshaling patch data: %w", err)
|
||||
}
|
||||
|
||||
// Patch the status sub-resource
|
||||
unstructuredJob, err := crd.client.
|
||||
Namespace(job.GetNamespace()).
|
||||
Patch(
|
||||
context.Background(),
|
||||
job.GetName(),
|
||||
types.MergePatchType, // Use MergePatchType for JSON Merge Patch
|
||||
patchBytes,
|
||||
metaV1.PatchOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
pkg.Logger.Error(
|
||||
"[crd] [status] error patching custom resource status",
|
||||
zap.String("namespace", job.GetNamespace()),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
newJob, err := convertFromUnstructured(unstructuredJob)
|
||||
if err != nil {
|
||||
pkg.Logger.Error("[crd] [status] error in structure unstructured patched", zap.Error(err))
|
||||
}
|
||||
jobs.Store(jobUid, newJob)
|
||||
if err != nil {
|
||||
pkg.Logger.Error("[crd] [status] ", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (crd Crd) PatchAll(patchData map[string]interface{}) error {
|
||||
keys := GetAllJobKeys()
|
||||
for _, key := range keys {
|
||||
err := crd.Patch(key, patchData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
29
internal/crd/repo.go
Normal file
29
internal/crd/repo.go
Normal file
@ -0,0 +1,29 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// var jobs = map[types.UID]*v1alpha1.FlinkJob{}
|
||||
var jobs = pkg.SafeMap[types.UID, *v1alpha1.FlinkJob]{}
|
||||
|
||||
func (crd *Crd) repsert(job *v1alpha1.FlinkJob) {
|
||||
jobs.Store(job.GetUID(), job)
|
||||
}
|
||||
|
||||
func GetJob(uid types.UID) v1alpha1.FlinkJob {
|
||||
job, _ := jobs.Load(uid)
|
||||
return *job.DeepCopy()
|
||||
}
|
||||
|
||||
func GetAllJobKeys() []types.UID {
|
||||
keys := []types.UID{}
|
||||
jobs.Range(func(k types.UID, value *v1alpha1.FlinkJob) bool {
|
||||
keys = append(keys, k)
|
||||
return true
|
||||
})
|
||||
return keys
|
||||
}
|
||||
15
internal/crd/status.go
Normal file
15
internal/crd/status.go
Normal file
@ -0,0 +1,15 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
func (crd Crd) SetJobStatus(jobUid types.UID, status v1alpha1.FlinkJobStatus) error {
|
||||
// Define the patch data (JSON Merge Patch format)
|
||||
patchData := map[string]interface{}{
|
||||
"status": status,
|
||||
}
|
||||
return crd.Patch(jobUid, patchData)
|
||||
}
|
||||
12
internal/crd/types.go
Normal file
12
internal/crd/types.go
Normal file
@ -0,0 +1,12 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type FlinkJobCrdEvent struct {
|
||||
EventType watch.EventType
|
||||
Job *v1alpha1.FlinkJob
|
||||
}
|
||||
87
internal/crd/v1alpha1/flink_job.go
Normal file
87
internal/crd/v1alpha1/flink_job.go
Normal file
@ -0,0 +1,87 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
//go:generate go run sigs.k8s.io/controller-tools/cmd/controller-gen object paths=$GOFILE
|
||||
|
||||
type FlinkJobSpec struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Parallelism int `json:"parallelism"`
|
||||
JarURI string `json:"jarUri"`
|
||||
SavepointInterval metaV1.Duration `json:"savepointInterval"`
|
||||
EntryClass string `json:"entryClass"`
|
||||
}
|
||||
|
||||
type FlinkJobStatus struct {
|
||||
JobStatus JobStatus `json:"jobStatus,omitempty"`
|
||||
LifeCycleStatus LifeCycleStatus `json:"lifeCycleStatus,omitempty"`
|
||||
LastSavepointPath *string `json:"lastSavepointPath,omitempty"`
|
||||
JarId *string `json:"jarId,omitempty"`
|
||||
JobId *string `json:"jobId,omitempty"`
|
||||
Error *string `json:"error,omitempty"`
|
||||
SavepointTriggerId *string `json:"savepointTriggerId,omitempty"`
|
||||
PauseSavepointTriggerId *string `json:"pauseSavepointTriggerId,omitempty"`
|
||||
LastSavepointDate *time.Time `json:"lastSavepointDate,omitempty"`
|
||||
LastRestoredSavepointDate *time.Time `json:"lastRestoredSavepointDate,omitempty"`
|
||||
LastRestoredSavepointRestoredDate *time.Time `json:"lastRestoredSavepointRestoredDate,omitempty"`
|
||||
RestoredCount int `json:"restoredCount,omitempty"`
|
||||
RunningJarURI *string `json:"runningJarURI"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type FlinkJob struct {
|
||||
metaV1.TypeMeta `json:",inline"`
|
||||
metaV1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec FlinkJobSpec `json:"spec"`
|
||||
Status FlinkJobStatus `json:"status"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type FlinkJobList struct {
|
||||
metaV1.TypeMeta `json:",inline"`
|
||||
metaV1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []FlinkJob `json:"items"`
|
||||
}
|
||||
|
||||
var (
|
||||
ErrNoJobId = errors.New("[managed-job] no job id")
|
||||
ErrNoJarId = errors.New("[managed-job] no jar id")
|
||||
ErrNoSavepointTriggerId = errors.New("[managed-job] no savepoint trigger id")
|
||||
ErrNoSavepointPath = errors.New("[managed-job] no savepoint path")
|
||||
)
|
||||
|
||||
type JobStatus string
|
||||
|
||||
var (
|
||||
JobStatusInitializing JobStatus = "INITIALIZING"
|
||||
JobStatusRunning JobStatus = "RUNNING"
|
||||
JobStatusCreating JobStatus = "CREATING"
|
||||
JobStatusError JobStatus = "ERROR"
|
||||
JobStatusReconciling JobStatus = "RECONCILING"
|
||||
JobStatusFailed JobStatus = "FAILED"
|
||||
JobStatusFailing JobStatus = "FAILING"
|
||||
JobStatusRestarting JobStatus = "RESTARTING"
|
||||
JobStatusFinished JobStatus = "FINISHED"
|
||||
JobStatusCanceled JobStatus = "CANCELED"
|
||||
JobStatusCancelling JobStatus = "CANCELLING"
|
||||
JobStatusSuspended JobStatus = "SUSPENDED"
|
||||
)
|
||||
|
||||
type LifeCycleStatus string
|
||||
|
||||
const (
|
||||
LifeCycleStatusInitializing LifeCycleStatus = "INITIALIZING"
|
||||
LifeCycleStatusRestoring LifeCycleStatus = "RESTORING"
|
||||
LifeCycleStatusGracefulStopFailed LifeCycleStatus = "GRACEFUL_STOP_FAILED"
|
||||
LifeCycleStatusUpgradeFailed LifeCycleStatus = "UPGRADE_FAILED"
|
||||
LifeCycleStatusGracefullyPaused LifeCycleStatus = "GRACEFULLY_PAUSED"
|
||||
LifeCycleStatusUnhealthyJobManager LifeCycleStatus = "UNHEALTHY_JOB_MANAGER"
|
||||
LifeCycleStatusHealthy LifeCycleStatus = "HEALTHY"
|
||||
LifeCycleStatusFailed LifeCycleStatus = "FAILED"
|
||||
)
|
||||
35
internal/crd/v1alpha1/register.go
Normal file
35
internal/crd/v1alpha1/register.go
Normal file
@ -0,0 +1,35 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
const GroupName = "flink.logicamp.tech"
|
||||
const GroupVersion = "v1alpha1"
|
||||
const ResourceName = "flink-jobs"
|
||||
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: GroupVersion}
|
||||
|
||||
// Define the FlinkJob resource GVR (Group, Version, Resource)
|
||||
var FlinkJobGVR = schema.GroupVersionResource{
|
||||
Group: GroupName,
|
||||
Version: GroupVersion,
|
||||
Resource: ResourceName,
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&FlinkJob{},
|
||||
&FlinkJobList{},
|
||||
)
|
||||
|
||||
metaV1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
67
internal/crd/v1alpha1/zz_generated.deepcopy.go
Normal file
67
internal/crd/v1alpha1/zz_generated.deepcopy.go
Normal file
@ -0,0 +1,67 @@
|
||||
//go:build !ignore_autogenerated
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
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 *FlinkJob) DeepCopyInto(out *FlinkJob) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlinkJob.
|
||||
func (in *FlinkJob) DeepCopy() *FlinkJob {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FlinkJob)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *FlinkJob) 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 *FlinkJobList) DeepCopyInto(out *FlinkJobList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]FlinkJob, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlinkJobList.
|
||||
func (in *FlinkJobList) DeepCopy() *FlinkJobList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FlinkJobList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *FlinkJobList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
65
internal/crd/watch.go
Normal file
65
internal/crd/watch.go
Normal file
@ -0,0 +1,65 @@
|
||||
package crd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"github.com/reactivex/rxgo/v2"
|
||||
"go.uber.org/zap"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
func (crd Crd) watchFlinkJobs() rxgo.Observable {
|
||||
|
||||
ch := make(chan rxgo.Item)
|
||||
|
||||
go func() {
|
||||
pkg.Logger.Debug("[crd] starting watch")
|
||||
watcher, err := crd.client.Watch(context.Background(), metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer watcher.Stop()
|
||||
for event := range watcher.ResultChan() {
|
||||
pkg.Logger.Debug("[crd] event received", zap.Any("type", event.Type))
|
||||
unstructuredJob := event.Object.(*unstructured.Unstructured)
|
||||
unstructuredMap, _, err := unstructured.NestedMap(unstructuredJob.Object)
|
||||
if err != nil {
|
||||
pkg.Logger.Error("cannot create unstructured map", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
job := &v1alpha1.FlinkJob{}
|
||||
|
||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredMap, job)
|
||||
if err != nil {
|
||||
pkg.Logger.Error("cannot convert unstructured to structured", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- rxgo.Item{
|
||||
V: &FlinkJobCrdEvent{
|
||||
EventType: event.Type,
|
||||
Job: job,
|
||||
},
|
||||
}
|
||||
switch event.Type {
|
||||
case watch.Bookmark:
|
||||
case watch.Modified:
|
||||
pkg.Logger.Info("[crd] [watch] flink job modified", zap.String("jobName", job.GetName()))
|
||||
crd.repsert(job)
|
||||
case watch.Added:
|
||||
pkg.Logger.Info("[crd] [watch] new flink job created")
|
||||
crd.repsert(job)
|
||||
case watch.Deleted:
|
||||
}
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
return rxgo.FromChannel(ch)
|
||||
}
|
||||
@ -7,7 +7,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gitea.com/logicamp/lc"
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
gonanoid "github.com/matoous/go-nanoid/v2"
|
||||
"go.uber.org/zap"
|
||||
@ -29,23 +30,24 @@ func NewJarFile(URI string) (*JarFile, error) {
|
||||
return jarFile, nil
|
||||
}
|
||||
|
||||
func (JarFile JarFile) Upload(flinkClient *api.Client) (fileName string, err error) {
|
||||
func (jarFile *JarFile) Upload(flinkClient *api.Client) (fileName string, err error) {
|
||||
|
||||
resp, err := flinkClient.UploadJar(JarFile.filePath)
|
||||
resp, err := flinkClient.UploadJar(jarFile.filePath)
|
||||
if err != nil {
|
||||
lc.Logger.Error("[main] error uploading jar", zap.Error(err))
|
||||
pkg.Logger.Error("[main] error uploading jar", zap.Error(err))
|
||||
}
|
||||
filePathParts := strings.Split(resp.FileName, "/")
|
||||
fileName = filePathParts[len(filePathParts)-1]
|
||||
if resp.Status != "success" {
|
||||
err = errors.New("jar upload was not success")
|
||||
}
|
||||
jarFile.delete()
|
||||
return
|
||||
}
|
||||
|
||||
func (jarFile *JarFile) Download() error {
|
||||
fileName, _ := gonanoid.New()
|
||||
jarFile.filePath = fileName + ".jar"
|
||||
jarFile.filePath = "/tmp/" + fileName + ".jar"
|
||||
out, err := os.Create(jarFile.filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -53,7 +55,8 @@ func (jarFile *JarFile) Download() error {
|
||||
|
||||
defer out.Close()
|
||||
resp, err := http.Get(jarFile.uri)
|
||||
if err != nil {
|
||||
if err != nil || resp.StatusCode > 299 {
|
||||
jarFile.delete()
|
||||
return err
|
||||
}
|
||||
|
||||
@ -65,6 +68,11 @@ func (jarFile *JarFile) Download() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (jarFile JarFile) Delete() error {
|
||||
return os.Remove(jarFile.filePath)
|
||||
func (jarFile *JarFile) delete() error {
|
||||
pkg.Logger.Info("[jar] [delete]", zap.String("path", jarFile.filePath))
|
||||
err := os.Remove(jarFile.filePath)
|
||||
if err != nil {
|
||||
pkg.Logger.Error("[jar] [delete]", zap.Error(err))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1,71 +1,54 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"time"
|
||||
|
||||
"gitea.com/logicamp/lc"
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (job *ManagedJob) startCycle() {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
quit := make(chan struct{})
|
||||
|
||||
// load job state from db
|
||||
job.loadState()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
job.cycle()
|
||||
case <-quit:
|
||||
ticker.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (job *ManagedJob) cycle() {
|
||||
lc.Logger.Debug("[managed-job] [new] check cycle", zap.String("jobKey", job.def.Key))
|
||||
func (job *ManagedJob) Cycle() {
|
||||
pkg.Logger.Debug("[managed-job] [new] check cycle", zap.String("jobName", job.def.GetName()))
|
||||
|
||||
// Init job
|
||||
if job.state == nil {
|
||||
err := job.upload()
|
||||
if err != nil {
|
||||
job.setError("[upload-error] " + err.Error())
|
||||
return
|
||||
}
|
||||
err = job.run()
|
||||
if err != nil {
|
||||
job.setError("[run-error] " + err.Error())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
// Check for set running or error state
|
||||
if job.state.Status == JobStatusCreating {
|
||||
err := job.checkStatus()
|
||||
if errors.Is(err, ErrNoJobId) {
|
||||
job.state = nil
|
||||
}
|
||||
if job.def.Status.LifeCycleStatus == "" && job.def.Status.JobStatus == "" {
|
||||
job.run(false)
|
||||
return
|
||||
}
|
||||
|
||||
if job.state.Status == JobStatusRunning {
|
||||
err := job.checkStatus()
|
||||
if errors.Is(err, ErrNoJobId) {
|
||||
job.state = nil
|
||||
}
|
||||
if job.state.LastSavepointDate == nil || time.Now().Add(-job.def.SavepointInterval).After(*job.state.LastSavepointDate) {
|
||||
if job.state.SavepointTriggerId == nil {
|
||||
if job.def.Status.JobStatus == v1alpha1.JobStatusFinished && job.def.Status.LifeCycleStatus == v1alpha1.LifeCycleStatusGracefullyPaused {
|
||||
job.run(true)
|
||||
return
|
||||
}
|
||||
|
||||
if job.def.Status.JobStatus == v1alpha1.JobStatusRunning {
|
||||
if (job.def.Spec.SavepointInterval.Duration != 0) && ((job.def.Status.LastSavepointDate == nil) || time.Now().Add(-job.def.Spec.SavepointInterval.Duration).After(*job.def.Status.LastSavepointDate)) {
|
||||
if job.def.Status.SavepointTriggerId == nil {
|
||||
job.createSavepoint()
|
||||
} else {
|
||||
job.trackSavepoint()
|
||||
}
|
||||
}
|
||||
if job.def.Status.RunningJarURI != nil && job.def.Spec.JarURI != *job.def.Status.RunningJarURI {
|
||||
job.upgrade()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if job.def.Status.JobStatus == v1alpha1.JobStatusCreating {
|
||||
return
|
||||
}
|
||||
// if job.def.Status.JobStatus == v1alpha1.JobStatusFailed && job.def.Status.LastSavepointPath != nil {
|
||||
// //job.restore()
|
||||
// return
|
||||
// }
|
||||
// if job.def.Status.JobStatus == v1alpha1.JobStatusFailed && job.def.Status.LastSavepointPath == nil {
|
||||
// //job.restore()
|
||||
// return
|
||||
// }
|
||||
|
||||
pkg.Logger.Warn("[managed-job] [cycle]", zap.String("unhanded job status", string(job.def.Status.JobStatus)))
|
||||
}
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/config"
|
||||
"flink-kube-operator/internal/crd"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
)
|
||||
|
||||
type ManagedJob struct {
|
||||
def config.JobDef
|
||||
def v1alpha1.FlinkJob
|
||||
client *api.Client
|
||||
jarId string
|
||||
db *badger.DB
|
||||
state *jobState
|
||||
crd *crd.Crd
|
||||
}
|
||||
|
||||
func NewManagedJob(client *api.Client, db *badger.DB, def config.JobDef) *ManagedJob {
|
||||
func NewManagedJob(client *api.Client, def v1alpha1.FlinkJob, crd *crd.Crd) *ManagedJob {
|
||||
job := &ManagedJob{
|
||||
def: def,
|
||||
client: client,
|
||||
db: db,
|
||||
crd: crd,
|
||||
}
|
||||
job.startCycle()
|
||||
//job.startCycle()
|
||||
return job
|
||||
}
|
||||
|
||||
func (job *ManagedJob) Update(def v1alpha1.FlinkJob) {
|
||||
job.def = def
|
||||
}
|
||||
|
||||
71
internal/managed_job/pause.go
Normal file
71
internal/managed_job/pause.go
Normal file
@ -0,0 +1,71 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"flink-kube-operator/pkg"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (job *ManagedJob) pause() error {
|
||||
var err error
|
||||
if job.def.Status.JobId != nil {
|
||||
result, stopJobErr := job.client.StopJobWithSavepoint(*job.def.Status.JobId, os.Getenv("SAVEPOINT_PATH"), false)
|
||||
if stopJobErr != nil {
|
||||
err = stopJobErr
|
||||
pkg.Logger.Error("[managed-job] [pause] cannot stop job", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
var savepointPath string
|
||||
for {
|
||||
trackResult, err := job.client.TrackSavepoint(*job.def.Status.JobId, result.RequestID)
|
||||
time.Sleep(time.Millisecond * 500)
|
||||
if err == nil && trackResult.Status.Id == api.SavepointStatusInCompleted {
|
||||
if trackResult.Operation.Location != "" {
|
||||
savepointPath = trackResult.Operation.Location
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if savepointPath != "" {
|
||||
job.def.Status.LastSavepointPath = &savepointPath
|
||||
job.def.Status.PauseSavepointTriggerId = nil
|
||||
job.def.Status.JobStatus = ""
|
||||
job.def.Status.LastSavepointPath = &savepointPath
|
||||
lastSavepointDate := time.Now()
|
||||
job.def.Status.LastSavepointDate = &lastSavepointDate
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"jobStatus": "FINISHED",
|
||||
"lifeCycleStatus": v1alpha1.LifeCycleStatusGracefullyPaused,
|
||||
"savepointTriggerId": nil,
|
||||
"lastSavepointPath": savepointPath,
|
||||
"lastSavepointDate": lastSavepointDate.Format(time.RFC3339),
|
||||
},
|
||||
})
|
||||
pkg.Logger.Info(
|
||||
"[managed-job] job paused successfully",
|
||||
zap.String("jobName", job.def.GetName()),
|
||||
zap.String("savepointPath", savepointPath),
|
||||
)
|
||||
} else {
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"lifeCycleStatus": v1alpha1.LifeCycleStatusGracefulStopFailed,
|
||||
"lastSavepointPath": savepointPath,
|
||||
"lastSavepointDate": time.Now().Format(time.RFC3339),
|
||||
},
|
||||
})
|
||||
pkg.Logger.Error(
|
||||
"[managed-job] error in pausing job",
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
5
internal/managed_job/remove.go
Normal file
5
internal/managed_job/remove.go
Normal file
@ -0,0 +1,5 @@
|
||||
package managed_job
|
||||
|
||||
func (job *ManagedJob) Stop() {
|
||||
job.client.StopJob(*job.def.Status.JobId)
|
||||
}
|
||||
@ -1,46 +1,91 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/jar"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"gitea.com/logicamp/lc"
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// upload jar file and set the jarId for later usages
|
||||
func (job *ManagedJob) upload() error {
|
||||
jarFile, err := jar.NewJarFile(job.def.JarURI)
|
||||
if err != nil {
|
||||
lc.Logger.Debug("[main] error on download jar", zap.Error(err))
|
||||
return err
|
||||
// run the job from savepoint and jarId in managedJob
|
||||
func (job *ManagedJob) run(restoreMode bool) error {
|
||||
var savepointPath string
|
||||
if job.def.Status.LastSavepointPath == nil {
|
||||
pkg.Logger.Error("[managed-job] [restore]", zap.Error(v1alpha1.ErrNoSavepointPath))
|
||||
if restoreMode {
|
||||
return v1alpha1.ErrNoSavepointPath
|
||||
}
|
||||
} else {
|
||||
savepointPath = *job.def.Status.LastSavepointPath
|
||||
}
|
||||
fileName, err := jarFile.Upload(job.client)
|
||||
jarFile.Delete()
|
||||
if err != nil {
|
||||
lc.Logger.Debug("[main] error on upload jar", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
lc.Logger.Debug("[main] after upload jar", zap.Any("upload-jar-resp", fileName))
|
||||
|
||||
job.jarId = fileName
|
||||
pkg.Logger.Info(
|
||||
"[managed-job] [restore] starting job...",
|
||||
zap.Bool("restoreMode", restoreMode),
|
||||
zap.String("name", job.def.GetName()),
|
||||
zap.String("savepointPath", savepointPath),
|
||||
)
|
||||
var jobId *string
|
||||
for {
|
||||
shouldUpload := false
|
||||
if job.def.Status.JarId == nil {
|
||||
err := v1alpha1.ErrNoJarId
|
||||
pkg.Logger.Warn("[managed-job] [run] will upload new jar...", zap.Error(err))
|
||||
shouldUpload = true
|
||||
} else {
|
||||
runJarResp, err := job.client.RunJar(api.RunOpts{
|
||||
JarID: *job.def.Status.JarId,
|
||||
AllowNonRestoredState: true,
|
||||
EntryClass: job.def.Spec.EntryClass,
|
||||
SavepointPath: savepointPath,
|
||||
})
|
||||
if err == nil {
|
||||
pkg.Logger.Info("[managed-job] [run] jar successfully ran", zap.Any("run-jar-resp", runJarResp))
|
||||
jobId = &runJarResp.JobId
|
||||
break
|
||||
} else {
|
||||
if strings.ContainsAny(err.Error(), ".jar does not exist") {
|
||||
shouldUpload = true
|
||||
} else {
|
||||
pkg.Logger.Error("[managed-job] [run] unhandled jar run Flink error", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if shouldUpload {
|
||||
err := job.upload()
|
||||
if err != nil {
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"error": "[upload-error] " + err.Error(),
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// job.def.Status.JobId = &runJarResp.JobId
|
||||
// job.def.Status.JobStatus = v1alpha1.JobStatusCreating
|
||||
// job.def.Status.Error = nil
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"jobId": jobId,
|
||||
"runningJarURI": job.def.Spec.JarURI,
|
||||
"jobStatus": v1alpha1.JobStatusCreating,
|
||||
"lifeCycleStatus": v1alpha1.LifeCycleStatusRestoring,
|
||||
"lastRestoredSavepointDate": job.def.Status.LastSavepointDate,
|
||||
"restoredCount": job.def.Status.RestoredCount + 1,
|
||||
"lastRestoredSavepointRestoredDate": time.Now().Format(time.RFC3339),
|
||||
"error": nil,
|
||||
},
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// run the job from saved jarId in managedJob
|
||||
func (job *ManagedJob) run() error {
|
||||
runJarResp, err := job.client.RunJar(api.RunOpts{
|
||||
JarID: job.jarId,
|
||||
AllowNonRestoredState: true,
|
||||
EntryClass: job.def.EntryClass,
|
||||
})
|
||||
if err != nil {
|
||||
lc.Logger.Error("[managed-job] [run]", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
lc.Logger.Debug("[main] after run jar", zap.Any("run-jar-resp", runJarResp))
|
||||
|
||||
job.updateState(jobState{JobId: &runJarResp.JobId, Status: JobStatusCreating})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1,46 +1,81 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"gitea.com/logicamp/lc"
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (job ManagedJob) createSavepoint() error {
|
||||
if job.state.JobId == nil {
|
||||
lc.Logger.Debug("[managed-job] [savepoint] no job id")
|
||||
return ErrNoJobId
|
||||
if job.def.Status.JobId == nil {
|
||||
pkg.Logger.Debug("[managed-job] [savepoint] no job id")
|
||||
return v1alpha1.ErrNoJobId
|
||||
}
|
||||
resp, err := job.client.SavePoints(*job.state.JobId, "/flink-data/savepoints-2/", false)
|
||||
pkg.Logger.Info("[managed-job] [savepoint] creating savepoint", zap.String("interval", job.def.Spec.SavepointInterval.String()))
|
||||
resp, err := job.client.SavePoints(*job.def.Status.JobId, os.Getenv("SAVEPOINT_PATH"), false)
|
||||
if err != nil {
|
||||
lc.Logger.Error("[managed-job] [savepoint] error in creating savepoint", zap.Error(err))
|
||||
pkg.Logger.Error("[managed-job] [savepoint] error in creating savepoint", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
lc.Logger.Debug("[managed-job] [savepoint]", zap.Any("savepoint-resp", resp))
|
||||
job.setSavepointTriggerId(resp.RequestID)
|
||||
pkg.Logger.Debug("[managed-job] [savepoint] savepoint created successfully", zap.String("trigger-id", resp.RequestID))
|
||||
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"savepointTriggerId": resp.RequestID,
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (job ManagedJob) trackSavepoint() error {
|
||||
if job.state.JobId == nil {
|
||||
lc.Logger.Debug("[managed-job] [savepoint] no job id")
|
||||
return ErrNoJobId
|
||||
if job.def.Status.JobId == nil {
|
||||
pkg.Logger.Debug("[managed-job] [savepoint] no job id")
|
||||
return v1alpha1.ErrNoJobId
|
||||
}
|
||||
if job.state.SavepointTriggerId == nil {
|
||||
lc.Logger.Debug("[managed-job] [savepoint] no job id")
|
||||
return ErrNoSavepointTriggerId
|
||||
if job.def.Status.SavepointTriggerId == nil {
|
||||
pkg.Logger.Debug("[managed-job] [savepoint] no job id")
|
||||
return v1alpha1.ErrNoSavepointTriggerId
|
||||
}
|
||||
resp, err := job.client.TrackSavepoint(*job.state.JobId, *job.state.SavepointTriggerId)
|
||||
lc.Logger.Debug("[managed-job] [savepoint] track savepoint", zap.Any("resp", resp), zap.Error(err))
|
||||
if err != nil {
|
||||
if strings.IndexAny(err.Error(), "http status not 2xx: 404") == 0 {
|
||||
job.removeSavepointTriggerId()
|
||||
resp, err := job.client.TrackSavepoint(*job.def.Status.JobId, *job.def.Status.SavepointTriggerId)
|
||||
pkg.Logger.Info("[managed-job] [savepoint] savepoint track result",
|
||||
zap.Any("status.Id", resp.Status.Id),
|
||||
zap.Any("path", resp.Operation.Location),
|
||||
zap.Any("failureCause.stacktrace", resp.Operation.FailureCause.StackTrace),
|
||||
zap.Any("failureCause.class", resp.Operation.FailureCause.Class),
|
||||
zap.Error(err),
|
||||
)
|
||||
if err != nil || resp.Operation.FailureCause.Class != "" {
|
||||
if err != nil {
|
||||
if strings.IndexAny(err.Error(), "http status not 2xx: 404") == 0 {
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"savepointTriggerId": nil,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"error": resp.Operation.FailureCause.StackTrace,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if resp.Status.Id == api.SavepointStatusInCompleted {
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"savepointTriggerId": nil,
|
||||
"lastSavepointPath": resp.Operation.Location,
|
||||
"lastSavepointDate": time.Now().Format(time.RFC3339),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
if resp.Status.Id == api.SavepointStatusInCompleted {
|
||||
job.setSavepointLocation(resp.Operation.Location)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -1,71 +1,78 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
// import (
|
||||
// "encoding/json"
|
||||
// "flink-kube-operator/internal/crd/v1alpha1"
|
||||
// "time"
|
||||
|
||||
"github.com/dgraph-io/badger/v4"
|
||||
)
|
||||
// "github.com/tidwall/buntdb"
|
||||
// )
|
||||
|
||||
// get state of job from local db
|
||||
func (job *ManagedJob) loadState() {
|
||||
err := job.db.View(
|
||||
func(tx *badger.Txn) error {
|
||||
if val, err := tx.Get([]byte(job.def.Key)); err != nil {
|
||||
return err
|
||||
} else if val != nil {
|
||||
val.Value(func(val []byte) error {
|
||||
job.state = &jobState{}
|
||||
return json.Unmarshal(val, job.state)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if errors.Is(err, badger.ErrKeyNotFound) {
|
||||
err = nil
|
||||
// // get state of job from local db
|
||||
// func (job *ManagedJob) loadState() {
|
||||
// job.db.View(
|
||||
// func(tx *buntdb.Tx) error {
|
||||
// if val, err := tx.Get(string(job.def.GetUID())); err != nil {
|
||||
// return err
|
||||
// } else {
|
||||
// return json.Unmarshal([]byte(val), job.state)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// // save state of job to local db
|
||||
// func (job *ManagedJob) updateState(state jobState) {
|
||||
// job.state = &state
|
||||
|
||||
// value, _ := json.Marshal(job.state)
|
||||
// job.db.Update(func(tx *buntdb.Tx) error {
|
||||
// _, _, err := tx.Set(string(job.def.GetUID()), string(value), nil)
|
||||
// return err
|
||||
// })
|
||||
// }
|
||||
|
||||
// func (job *ManagedJob) setError(errMsg string) {
|
||||
// if job.state == nil {
|
||||
// job.state = &jobState{}
|
||||
// }
|
||||
// job.state.Error = &errMsg
|
||||
// job.state.Status = v1alpha1.JobStatusError
|
||||
// job.updateState(*job.state)
|
||||
// job.crd.SetJobStatus(job.def.UID, v1alpha1.FlinkJobStatus{
|
||||
// JobStatus: job.state.Status,
|
||||
// })
|
||||
// }
|
||||
|
||||
// func (job *ManagedJob) setSavepointLocation(savepointId string) {
|
||||
// job.state.LastSavepointPath = &savepointId
|
||||
// job.state.SavepointTriggerId = nil
|
||||
// n := time.Now()
|
||||
// job.state.LastSavepointDate = &n
|
||||
// job.updateState(*job.state)
|
||||
// job.crd.SetJobStatus(job.def.UID, v1alpha1.FlinkJobStatus{
|
||||
// LastSavepointPath: job.state.LastSavepointPath,
|
||||
// })
|
||||
// }
|
||||
|
||||
// func (job *ManagedJob) setSavepointTriggerId(savepointReqId string) {
|
||||
// job.state.SavepointTriggerId = &savepointReqId
|
||||
// job.updateState(*job.state)
|
||||
// }
|
||||
|
||||
// func (job *ManagedJob) removeSavepointTriggerId() {
|
||||
// job.state.SavepointTriggerId = nil
|
||||
// job.updateState(*job.state)
|
||||
// }
|
||||
|
||||
// func (job *ManagedJob) SetStatus(status JobStatus) {
|
||||
// job.state.Status = status
|
||||
// job.updateState(*job.state)
|
||||
// }
|
||||
|
||||
func (job *ManagedJob) GetJobId() *string {
|
||||
if job.def.Status.JobId != nil {
|
||||
return job.def.Status.JobId
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// save state of job to local db
|
||||
func (job *ManagedJob) updateState(state jobState) {
|
||||
job.state = &state
|
||||
|
||||
value, _ := json.Marshal(job.state)
|
||||
job.db.Update(func(txn *badger.Txn) error {
|
||||
err := txn.Set([]byte(job.def.Key), value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return txn.Commit()
|
||||
})
|
||||
}
|
||||
|
||||
func (job *ManagedJob) setError(errMsg string) {
|
||||
job.state.Error = &errMsg
|
||||
job.state.Status = JobStatusError
|
||||
job.updateState(*job.state)
|
||||
}
|
||||
|
||||
func (job *ManagedJob) setSavepointLocation(savepointId string) {
|
||||
job.state.LastSavepointLocation = &savepointId
|
||||
job.state.SavepointTriggerId = nil
|
||||
n := time.Now()
|
||||
job.state.LastSavepointDate = &n
|
||||
job.updateState(*job.state)
|
||||
}
|
||||
|
||||
func (job *ManagedJob) setSavepointTriggerId(savepointReqId string) {
|
||||
job.state.SavepointTriggerId = &savepointReqId
|
||||
job.updateState(*job.state)
|
||||
}
|
||||
|
||||
func (job *ManagedJob) removeSavepointTriggerId() {
|
||||
job.state.SavepointTriggerId = nil
|
||||
job.updateState(*job.state)
|
||||
}
|
||||
|
||||
func (job *ManagedJob) setStatus(status JobStatus) {
|
||||
job.state.Status = status
|
||||
job.updateState(*job.state)
|
||||
}
|
||||
|
||||
@ -1,29 +1,45 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"strings"
|
||||
|
||||
"gitea.com/logicamp/lc"
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (job *ManagedJob) checkStatus() error {
|
||||
if job.state.JobId == nil {
|
||||
lc.Logger.Debug("[managed-job] [status] no job id")
|
||||
return ErrNoJobId
|
||||
if job.def.Status.JobId == nil {
|
||||
pkg.Logger.Debug("[managed-job] [status] no job id")
|
||||
return v1alpha1.ErrNoJobId
|
||||
}
|
||||
statusResp, err := job.client.Job(*job.state.JobId)
|
||||
statusResp, err := job.client.Job(*job.def.Status.JobId)
|
||||
if err != nil {
|
||||
lc.Logger.Debug("[managed-job] [status] cannot fetch status", zap.Error(err))
|
||||
pkg.Logger.Debug("[managed-job] [status] cannot fetch status", zap.Error(err))
|
||||
if strings.IndexAny(err.Error(), "http status not 2xx: 404") == 0 {
|
||||
job.updateState(jobState{
|
||||
JobId: job.state.JobId,
|
||||
Status: JobStatusNotFound,
|
||||
// job.updateState(jobState{
|
||||
// JobId: job.state.JobId,
|
||||
// Status: v1alpha1.JobStatusNotFound,
|
||||
// })
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"jobId": &job.def.Status.JobId,
|
||||
"jobStatus": "",
|
||||
"lifeCycleStatus": v1alpha1.LifeCycleStatusFailed,
|
||||
"error": "Job not found",
|
||||
},
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
//lc.Logger.Debug("[managed-job] [status]", zap.Any("status-resp", statusResp))
|
||||
job.setStatus(JobStatus(statusResp.State))
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"jobId": &job.def.Status.JobId,
|
||||
"jobStatus": statusResp.State,
|
||||
"lifeCycleStatus": v1alpha1.LifeCycleStatusFailed,
|
||||
"error": "Job not found",
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1,31 +1,16 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"time"
|
||||
)
|
||||
|
||||
type JobStatus string
|
||||
|
||||
var (
|
||||
ErrNoJobId = errors.New("[managed-job] no job id")
|
||||
ErrNoSavepointTriggerId = errors.New("[managed-job] no savepoint trigger id")
|
||||
)
|
||||
|
||||
const (
|
||||
JobStatusRunning JobStatus = "RUNNING"
|
||||
JobStatusCreating JobStatus = "CREATING"
|
||||
JobStatusNotFound JobStatus = "NotFound"
|
||||
JobStatusError JobStatus = "ERROR"
|
||||
JobStatusReconciling JobStatus = "RECONCILING"
|
||||
)
|
||||
|
||||
type jobState struct {
|
||||
Status JobStatus `json:"status"`
|
||||
Error *string `json:"error"`
|
||||
Info *string `json:"info"`
|
||||
JobId *string `json:"job_id"`
|
||||
LastSavepointLocation *string `json:"last_savepoint_location"`
|
||||
SavepointTriggerId *string `json:"savepoint_trigger_id"`
|
||||
LastSavepointDate *time.Time `json:"last_savepoint_time"`
|
||||
Status v1alpha1.JobStatus `json:"status"`
|
||||
Error *string `json:"error"`
|
||||
Info *string `json:"info"`
|
||||
JobId *string `json:"job_id"`
|
||||
LastSavepointPath *string `json:"last_savepoint_location"`
|
||||
SavepointTriggerId *string `json:"savepoint_trigger_id"`
|
||||
LastSavepointDate *time.Time `json:"last_savepoint_time"`
|
||||
}
|
||||
|
||||
38
internal/managed_job/upgrade.go
Normal file
38
internal/managed_job/upgrade.go
Normal file
@ -0,0 +1,38 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (job *ManagedJob) upgrade() {
|
||||
pkg.Logger.Info("[managed-job] [upgrade] pausing... ",
|
||||
zap.String("jobName", job.def.GetName()),
|
||||
zap.String("currentJarURI", job.def.Spec.JarURI),
|
||||
zap.String("prevJarURI", *job.def.Status.RunningJarURI),
|
||||
)
|
||||
job.def.Status.JarId = nil
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"jarId": job.def.Status.JarId,
|
||||
},
|
||||
})
|
||||
err := job.pause()
|
||||
if err != nil {
|
||||
pkg.Logger.Error("[managed-job] [upgrade] error in pausing", zap.Error(err))
|
||||
return
|
||||
}
|
||||
pkg.Logger.Info("[managed-job] [upgrade] restoring... ",
|
||||
zap.String("jobName", job.def.GetName()),
|
||||
zap.String("currentJarURI", job.def.Spec.JarURI),
|
||||
zap.String("prevJarURI", *job.def.Status.RunningJarURI),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
err = job.run(true)
|
||||
if err != nil {
|
||||
pkg.Logger.Error("[managed-job] [upgrade] error in running", zap.Error(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
32
internal/managed_job/upload.go
Normal file
32
internal/managed_job/upload.go
Normal file
@ -0,0 +1,32 @@
|
||||
package managed_job
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/jar"
|
||||
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// upload jar file and set the jarId for later usages
|
||||
func (job *ManagedJob) upload() error {
|
||||
jarFile, err := jar.NewJarFile(job.def.Spec.JarURI)
|
||||
if err != nil {
|
||||
pkg.Logger.Debug("[manage-job] [upload] error on download jar", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
jarId, err := jarFile.Upload(job.client)
|
||||
if err != nil {
|
||||
pkg.Logger.Debug("[manage-job] [upload] error on upload jar", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
pkg.Logger.Info("[manage-job] [upload] uploaded", zap.Any("upload-jar-resp", jarId))
|
||||
|
||||
job.def.Status.JarId = &jarId
|
||||
job.crd.Patch(job.def.UID, map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"jarId": job.def.Status.JarId,
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
111
internal/manager/manager.go
Normal file
111
internal/manager/manager.go
Normal file
@ -0,0 +1,111 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"flink-kube-operator/internal/crd"
|
||||
"flink-kube-operator/internal/crd/v1alpha1"
|
||||
"flink-kube-operator/internal/managed_job"
|
||||
"time"
|
||||
|
||||
"flink-kube-operator/pkg"
|
||||
|
||||
api "github.com/logi-camp/go-flink-client"
|
||||
"github.com/samber/lo"
|
||||
"go.uber.org/zap"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
client *api.Client
|
||||
managedJobs map[types.UID]managed_job.ManagedJob
|
||||
processingJobsIds []types.UID
|
||||
}
|
||||
|
||||
func NewManager(client *api.Client, crdInstance *crd.Crd) Manager {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
quit := make(chan struct{})
|
||||
mgr := Manager{
|
||||
client: client,
|
||||
managedJobs: map[types.UID]managed_job.ManagedJob{},
|
||||
processingJobsIds: []types.UID{},
|
||||
}
|
||||
|
||||
mgr.cycle(client, crdInstance)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
mgr.cycle(client, crdInstance)
|
||||
case <-quit:
|
||||
ticker.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return mgr
|
||||
}
|
||||
|
||||
func (mgr *Manager) cycle(client *api.Client, crdInstance *crd.Crd) {
|
||||
jobManagerJobOverviews, jobManagerJobStatusError := mgr.client.JobsOverview()
|
||||
if jobManagerJobStatusError != nil {
|
||||
pkg.Logger.Error("[manager] [cycle] cannot check flink jobs status", zap.Error(jobManagerJobStatusError))
|
||||
crdInstance.PatchAll(map[string]interface{}{
|
||||
"status": map[string]interface{}{
|
||||
"lifeCycleStatus": v1alpha1.LifeCycleStatusUnhealthyJobManager,
|
||||
},
|
||||
})
|
||||
}
|
||||
//pkg.Logger.Debug("[manager] [cycle] overviews", zap.Any("overviews", jobsOverviews))
|
||||
|
||||
// Loop over job definitions as Kubernetes CRD
|
||||
for _, uid := range crd.GetAllJobKeys() {
|
||||
if lo.Contains(mgr.processingJobsIds, uid) {
|
||||
pkg.Logger.Warn("[manager] already in process", zap.Any("uid", uid))
|
||||
continue
|
||||
}
|
||||
|
||||
// Get job definition from Kubernetes CRD
|
||||
def := crd.GetJob(uid)
|
||||
mgr.processingJobsIds = append(mgr.processingJobsIds, uid)
|
||||
|
||||
// Check if job exists in manager managed jobs
|
||||
managedJob, ok := mgr.managedJobs[uid]
|
||||
if ok {
|
||||
managedJob.Update(def)
|
||||
} else {
|
||||
// Add job to manager managed job
|
||||
managedJob = *managed_job.NewManagedJob(client, def, crdInstance)
|
||||
}
|
||||
if jobManagerJobStatusError != nil {
|
||||
|
||||
}
|
||||
|
||||
jobManagerJobOverview, ok := lo.Find(jobManagerJobOverviews.Jobs, func(job api.JobOverview) bool {
|
||||
jobId := managedJob.GetJobId()
|
||||
if jobId != nil {
|
||||
return job.ID == *jobId
|
||||
}
|
||||
return false
|
||||
})
|
||||
if ok {
|
||||
pkg.Logger.Debug("[manager] read status from flink", zap.String("name", jobManagerJobOverview.Name), zap.String("state", jobManagerJobOverview.State))
|
||||
patchStatusObj := map[string]interface{}{
|
||||
"jobStatus": v1alpha1.JobStatus(jobManagerJobOverview.State),
|
||||
}
|
||||
if jobManagerJobOverview.State == string(v1alpha1.JobStatusRunning) {
|
||||
status := string(v1alpha1.LifeCycleStatusHealthy)
|
||||
patchStatusObj["lifeCycleStatus"] = &status
|
||||
}
|
||||
|
||||
crdInstance.Patch(uid, map[string]interface{}{
|
||||
"status": patchStatusObj,
|
||||
})
|
||||
}
|
||||
|
||||
managedJob.Cycle()
|
||||
mgr.managedJobs[uid] = managedJob
|
||||
|
||||
mgr.processingJobsIds = lo.Filter(mgr.processingJobsIds, func(current types.UID, i int) bool {
|
||||
return current != uid
|
||||
})
|
||||
}
|
||||
}
|
||||
93
pkg/logger.go
Normal file
93
pkg/logger.go
Normal file
@ -0,0 +1,93 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/mattn/go-colorable"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
type LoggerConfig struct {
|
||||
Level zapcore.Level
|
||||
Filename string
|
||||
MaxSize int
|
||||
MaxAge int
|
||||
MaxBackups int
|
||||
Compress bool
|
||||
ConsoleEncoding bool // true for Console output, false for JSON
|
||||
}
|
||||
|
||||
var loggerInstance *zap.Logger
|
||||
|
||||
// GetLogger returns a singleton logger instance
|
||||
func GetLogger(ctx context.Context, config LoggerConfig) *zap.Logger {
|
||||
if loggerInstance == nil {
|
||||
createOrUpdateInstance(config)
|
||||
}
|
||||
return loggerInstance
|
||||
}
|
||||
|
||||
func createOrUpdateInstance(config LoggerConfig) *zap.Logger {
|
||||
core := zapcore.NewTee(
|
||||
createFileCore(config),
|
||||
createStdoutCore(config),
|
||||
)
|
||||
loggerInstance = zap.New(core).WithOptions(
|
||||
zap.IncreaseLevel(config.Level),
|
||||
)
|
||||
return loggerInstance
|
||||
}
|
||||
|
||||
// createFileCore creates the file logging core
|
||||
func createFileCore(config LoggerConfig) zapcore.Core {
|
||||
fileEncoderConfig := zap.NewProductionEncoderConfig()
|
||||
fileEncoder := zapcore.NewJSONEncoder(fileEncoderConfig)
|
||||
|
||||
fileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
|
||||
Filename: config.Filename,
|
||||
MaxSize: config.MaxSize,
|
||||
MaxAge: config.MaxAge,
|
||||
MaxBackups: config.MaxBackups,
|
||||
Compress: config.Compress,
|
||||
})
|
||||
|
||||
return zapcore.NewCore(fileEncoder, fileWriteSyncer, zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl >= zapcore.ErrorLevel
|
||||
}))
|
||||
}
|
||||
|
||||
// createStdoutCore creates the stdout logging core based on config.ConsoleEncoding
|
||||
func createStdoutCore(config LoggerConfig) zapcore.Core {
|
||||
var encoder zapcore.Encoder
|
||||
encoderConfig := zap.NewDevelopmentEncoderConfig()
|
||||
encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
||||
encoderConfig.TimeKey = ""
|
||||
|
||||
if config.ConsoleEncoding {
|
||||
encoder = zapcore.NewConsoleEncoder(encoderConfig)
|
||||
} else {
|
||||
encoder = zapcore.NewJSONEncoder(encoderConfig)
|
||||
}
|
||||
|
||||
stdoutWriteSyncer := zapcore.AddSync(colorable.NewColorableStdout())
|
||||
|
||||
return zapcore.NewCore(encoder, stdoutWriteSyncer, zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return true
|
||||
}))
|
||||
}
|
||||
|
||||
func OverrideLoggerConfig(config LoggerConfig) {
|
||||
Logger = createOrUpdateInstance(config)
|
||||
}
|
||||
|
||||
var Logger = GetLogger(context.Background(), LoggerConfig{
|
||||
Level: zap.DebugLevel,
|
||||
Filename: "./tmp/error.log",
|
||||
MaxSize: 100,
|
||||
MaxAge: 90,
|
||||
MaxBackups: 30,
|
||||
Compress: true,
|
||||
ConsoleEncoding: true,
|
||||
})
|
||||
42
pkg/safemap.go
Normal file
42
pkg/safemap.go
Normal file
@ -0,0 +1,42 @@
|
||||
package pkg
|
||||
|
||||
import "sync"
|
||||
|
||||
// SafeMap is a type-safe wrapper around sync.Map
|
||||
type SafeMap[K comparable, V any] struct {
|
||||
m sync.Map
|
||||
}
|
||||
|
||||
// Store sets the value for a key.
|
||||
func (t *SafeMap[K, V]) Store(key K, value V) {
|
||||
t.m.Store(key, value)
|
||||
}
|
||||
|
||||
// Load returns the value for a key, and whether the key was found.
|
||||
func (t *SafeMap[K, V]) Load(key K) (V, bool) {
|
||||
value, ok := t.m.Load(key)
|
||||
if !ok {
|
||||
var zero V
|
||||
return zero, false
|
||||
}
|
||||
return value.(V), true
|
||||
}
|
||||
|
||||
// LoadOrStore returns the existing value for the key if present.
|
||||
// Otherwise, it stores and returns the given value.
|
||||
func (t *SafeMap[K, V]) LoadOrStore(key K, value V) (V, bool) {
|
||||
actual, loaded := t.m.LoadOrStore(key, value)
|
||||
return actual.(V), loaded
|
||||
}
|
||||
|
||||
// Delete removes the key and its value from the map.
|
||||
func (t *SafeMap[K, V]) Delete(key K) {
|
||||
t.m.Delete(key)
|
||||
}
|
||||
|
||||
// Range iterates over all key-value pairs in the map.
|
||||
func (t *SafeMap[K, V]) Range(f func(key K, value V) bool) {
|
||||
t.m.Range(func(key, value interface{}) bool {
|
||||
return f(key.(K), value.(V))
|
||||
})
|
||||
}
|
||||
16
start-cluster.sh
Normal file
16
start-cluster.sh
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Alternatively, start TaskManager in the foreground if necessary
|
||||
$FLINK_HOME/bin/taskmanager.sh start
|
||||
|
||||
# Start JobManager in the foreground
|
||||
$FLINK_HOME/bin/jobmanager.sh start-foreground
|
||||
|
||||
# If you want to submit a job and still keep the cluster alive, use this:
|
||||
if [[ -n "$FLINK_JOB" ]]; then
|
||||
echo "Running Flink job: $FLINK_JOB"
|
||||
$FLINK_HOME/bin/flink run -d $FLINK_JOB
|
||||
fi
|
||||
|
||||
# Keep the container running
|
||||
tail -f /dev/null # This will prevent the container from exiting
|
||||
24
workflow.drawio
Normal file
24
workflow.drawio
Normal file
@ -0,0 +1,24 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="30dsCBfVl47Qj7MCYPGI" name="Page-1">
|
||||
<mxGraphModel dx="889" dy="433" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="4" style="edgeStyle=none;html=1;" edge="1" parent="1" source="2" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="353" y="334" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="2" value="" style="sketch=0;html=1;dashed=0;whitespace=wrap;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];verticalLabelPosition=bottom;align=center;verticalAlign=top;shape=mxgraph.kubernetes.icon;prIcon=crd" vertex="1" parent="1">
|
||||
<mxGeometry x="197" y="310" width="50" height="48" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.sequential_data;whiteSpace=wrap;" vertex="1" parent="1">
|
||||
<mxGeometry x="662" y="284" width="100" height="100" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="5" value="" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.database;whiteSpace=wrap;" vertex="1" parent="1">
|
||||
<mxGeometry x="375" y="304" width="60" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
Loading…
x
Reference in New Issue
Block a user