Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ extensions_tag = $(REGISTRY)/agones-extensions:$(VERSION)
sidecar_tag = $(REGISTRY)/agones-sdk:$(VERSION)
allocator_tag = $(REGISTRY)/agones-allocator:$(VERSION)
ping_tag = $(REGISTRY)/agones-ping:$(VERSION)
processor_tag = $(REGISTRY)/agones-processor:$(VERSION)

ifeq ($(WITH_WINDOWS), 1)
sidecar_linux_amd64_tag = $(REGISTRY)/agones-sdk:$(VERSION)-linux-amd64
Expand All @@ -130,13 +131,17 @@ extensions_amd64_tag = $(extensions_tag)-amd64
extensions_arm64_tag = $(extensions_tag)-arm64
ping_amd64_tag = $(ping_tag)-amd64
ping_arm64_tag = $(ping_tag)-arm64
processor_amd64_tag = $(processor_tag)-amd64
processor_arm64_tag = $(processor_tag)-arm64

# build list of images to include in the manifest for the sidecar image.
push_sidecar_manifest = $(sidecar_linux_amd64_tag)
push_allocator_manifest = $(allocator_amd64_tag)
push_controller_manifest = $(controller_amd64_tag)
push_extensions_manifest = $(extensions_amd64_tag)
push_ping_manifest = $(ping_amd64_tag)
push_processor_manifest = $(processor_amd64_tag)

gomod_on = GO111MODULE=on

go_version_flags = -ldflags "-X agones.dev/agones/pkg.Version=$(VERSION)"
Expand Down Expand Up @@ -276,13 +281,14 @@ push_allocator_manifest += $(allocator_arm64_tag)
push_controller_manifest += $(controller_arm64_tag)
push_extensions_manifest += $(extensions_arm64_tag)
push_ping_manifest += $(ping_arm64_tag)
push_processor_manifest += $(processor_arm64_tag)
endif

# build all
build: build-images build-sdks

# build the docker images
build-images: build-controller-image build-extensions-image build-agones-sdk-image build-ping-image build-allocator-image
build-images: build-controller-image build-extensions-image build-agones-sdk-image build-ping-image build-allocator-image build-processor-image

# package the current agones helm chart
build-chart: RELEASE_VERSION ?= $(base_version)
Expand Down Expand Up @@ -420,7 +426,7 @@ test-install-yaml:
diff /tmp/agones-install/install.yaml.sorted /tmp/agones-install/install.current.yaml.sorted

# Push all the images up to $(REGISTRY)
push: push-controller-image push-extensions-image push-agones-sdk-image push-ping-image push-allocator-image
push: push-controller-image push-extensions-image push-agones-sdk-image push-ping-image push-allocator-image push-processor-image

# Installs the current development version of Agones into the Kubernetes cluster
install: ALWAYS_PULL_SIDECAR := true
Expand Down Expand Up @@ -705,6 +711,46 @@ build-allocator-image-amd64: $(ensure-build-image) build-allocator-binary build-
build-allocator-image-arm64: $(ensure-build-image) build-allocator-binary create-arm64-builder
docker buildx build --provenance false $(agones_path)/cmd/allocator/ --builder $(BUILDX_ARM64_BUILDER) --tag=$(allocator_arm64_tag) --build-arg ARCH=arm64 --platform linux/arm64 $(DOCKER_BUILD_ARGS)

# push the processor image
build-processor-binary: $(ensure-build-image) build-processor-binary-linux-amd64
ifeq ($(WITH_ARM64), 1)
build-processor-binary: build-processor-binary-linux-arm64
endif

build-processor-binary-linux-amd64: $(ensure-build-image)
$(GO_BUILD_LINUX_AMD64) \
-tags $(GO_BUILD_TAGS) -o $(go_build_base_path)/cmd/processor/bin/processor.linux.amd64 \
$(go_rebuild_flags) $(go_version_flags) -installsuffix cgo $(agones_package)/cmd/processor
build-processor-binary-linux-arm64: $(ensure-build-image)
$(GO_BUILD_LINUX_ARM64) \
-tags $(GO_BUILD_TAGS) -o $(go_build_base_path)/cmd/processor/bin/processor.linux.arm64 \
$(go_rebuild_flags) $(go_version_flags) -installsuffix cgo $(agones_package)/cmd/processor

# Build the image for the processor service
build-processor-image: build-processor-image-amd64
ifeq ($(WITH_ARM64), 1)
build-processor-image: build-processor-image-arm64
endif

build-processor-image-amd64: $(ensure-build-image) build-processor-binary build-licenses build-required-src-dist
docker build $(agones_path)/cmd/processor/ --tag=$(processor_amd64_tag) $(DOCKER_BUILD_ARGS)
# creating docker builder and then using that builder to build processor image in buildx command
build-processor-image-arm64: $(ensure-build-image) build-processor-binary create-arm64-builder
docker buildx build --provenance false --platform linux/arm64 --builder $(BUILDX_ARM64_BUILDER) --build-arg ARCH=arm64 $(agones_path)/cmd/processor/ --tag=$(processor_arm64_tag) $(DOCKER_BUILD_ARGS)

# Pushes up the processor image
push-processor-image: push-processor-image-amd64
ifeq ($(WITH_ARM64), 1)
push-processor-image: push-processor-image-arm64
endif
# Docker >=24.0.6
docker buildx imagetools create --tag $(processor_tag) $(push_processor_manifest)

push-processor-image-amd64: build-processor-image-amd64
docker push $(processor_amd64_tag)
push-processor-image-arm64: build-processor-image-arm64
$(MAKE) DOCKER_BUILD_ARGS=--push build-processor-image-arm64

# push the gameservers sidecar image
push-agones-sdk-image: push-agones-sdk-linux-image-amd64
ifeq ($(WITH_WINDOWS), 1)
Expand Down
2 changes: 1 addition & 1 deletion build/build-required-src-dist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ tar -zcf ${TMP_DEPS_SRC} -C ${SRC_ROOT}/vendor/ \
github.com/hashicorp/golang-lru \
github.com/hashicorp/hcl

for ddir in ${SRC_ROOT}/cmd/controller/bin/ ${SRC_ROOT}/cmd/extensions/bin/ ${SRC_ROOT}/cmd/ping/bin/ ${SRC_ROOT}/cmd/sdk-server/bin/ ${SRC_ROOT}/cmd/allocator/bin/ ; do
for ddir in ${SRC_ROOT}/cmd/controller/bin/ ${SRC_ROOT}/cmd/extensions/bin/ ${SRC_ROOT}/cmd/ping/bin/ ${SRC_ROOT}/cmd/sdk-server/bin/ ${SRC_ROOT}/cmd/allocator/bin/ ${SRC_ROOT}/cmd/processor/bin/ ; do
mkdir -p ${ddir}
cp ${TMP_DEPS_SRC} ${ddir}
done
Expand Down
2 changes: 1 addition & 1 deletion build/extract-licenses.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ while read -r entry; do
append_license ${LIBRARY} ${entry}
done <<< "$(find vendor/ -regextype posix-extended -iregex '.*LICENSE(\.txt)?')"

for ddir in ${SRC_ROOT}/cmd/controller/bin/ ${SRC_ROOT}/cmd/extensions/bin/ ${SRC_ROOT}/cmd/ping/bin/ ${SRC_ROOT}/cmd/sdk-server/bin/ ${SRC_ROOT}/cmd/allocator/bin/ ; do
for ddir in ${SRC_ROOT}/cmd/controller/bin/ ${SRC_ROOT}/cmd/extensions/bin/ ${SRC_ROOT}/cmd/ping/bin/ ${SRC_ROOT}/cmd/sdk-server/bin/ ${SRC_ROOT}/cmd/allocator/bin/ ${SRC_ROOT}/cmd/processor/bin/; do
mkdir -p ${ddir}
cp ${TMP_LICENSES} ${ddir}
done
Expand Down
1 change: 1 addition & 0 deletions build/includes/kind.mk
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ kind-push:
kind load docker-image $(controller_tag) --name="$(KIND_PROFILE)"
kind load docker-image $(ping_tag) --name="$(KIND_PROFILE)"
kind load docker-image $(allocator_tag) --name="$(KIND_PROFILE)"
kind load docker-image $(processor_tag) --name="$(KIND_PROFILE)"

# Runs e2e tests against our kind cluster
kind-test-e2e:
Expand Down
2 changes: 2 additions & 0 deletions build/includes/minikube.mk
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ minikube-push:
$(MINIKUBE) image load $(ping_amd64_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image load $(allocator_amd64_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image load $(extensions_amd64_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image load $(processor_amd64_tag) -p $(MINIKUBE_PROFILE)

$(MINIKUBE) image tag $(sidecar_linux_amd64_tag) $(sidecar_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image tag $(controller_amd64_tag) $(controller_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image tag $(ping_amd64_tag) $(ping_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image tag $(allocator_amd64_tag) $(allocator_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image tag $(extensions_amd64_tag) $(extensions_tag) -p $(MINIKUBE_PROFILE)
$(MINIKUBE) image tag $(processor_amd64_tag) $(processor_tag) -p $(MINIKUBE_PROFILE)

# Installs the current development version of Agones into the Kubernetes cluster.
# Use this instead of `make install`, as it disables PullAlways on the install.yaml
Expand Down
2 changes: 1 addition & 1 deletion build/includes/release.mk
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ post-build-release:

tag-deprecated-images:
previous_version=$(shell echo $(base_version) | awk -F. '{print $$1"."$$2-1"."$$3}'); \
images="agones-controller agones-extensions agones-sdk agones-allocator agones-ping"; \
images="agones-controller agones-extensions agones-sdk agones-allocator agones-ping agones-processor"; \
for image in $$images; do \
gcloud artifacts docker tags add ${release_registry}/$$image:$$previous_version ${release_registry}/$$image:deprecated-public-image-$$previous_version; \
done
1 change: 1 addition & 0 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ images:
- ${_REGISTRY}/agones-sdk
- ${_REGISTRY}/agones-ping
- ${_REGISTRY}/agones-allocator
- ${_REGISTRY}/agones-processor
logsBucket: gs://agones-build-logs
options:
machineType: E2_HIGHCPU_32
Expand Down
25 changes: 25 additions & 0 deletions cmd/processor/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2025 Google LLC All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

FROM gcr.io/distroless/static-debian12:nonroot

ARG ARCH=amd64
WORKDIR /

COPY ./bin/processor.linux.$ARCH /processor
COPY ./bin/LICENSES .
COPY ./bin/dependencies-src.tgz .

USER nonroot:nonroot
ENTRYPOINT ["/processor"]
208 changes: 208 additions & 0 deletions cmd/processor/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// Copyright 2025 Google LLC All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Processor
package main

import (
"context"
"os"
"strings"
"time"

"agones.dev/agones/pkg"
"agones.dev/agones/pkg/util/httpserver"
"agones.dev/agones/pkg/util/runtime"
"agones.dev/agones/pkg/util/signals"

"github.com/google/uuid"
"github.com/heptiolabs/healthcheck"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
leaderelection "k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
)

const (
logLevelFlag = "log-level"
leaderElectionFlag = "leader-election"
podNamespace = "pod-namespace"
leaseDurationFlag = "lease-duration"
renewDeadlineFlag = "renew-deadline"
retryPeriodFlag = "retry-period"
)

var (
logger = runtime.NewLoggerWithSource("main")
)

type processorConfig struct {
LogLevel string
LeaderElection bool
PodNamespace string
LeaseDuration time.Duration
RenewDeadline time.Duration
RetryPeriod time.Duration
}

func parseEnvFlags() processorConfig {
viper.SetDefault(logLevelFlag, "Info")
viper.SetDefault(leaderElectionFlag, false)
viper.SetDefault(podNamespace, "")
viper.SetDefault(leaseDurationFlag, 15*time.Second)
viper.SetDefault(renewDeadlineFlag, 10*time.Second)
viper.SetDefault(retryPeriodFlag, 2*time.Second)

pflag.String(logLevelFlag, viper.GetString(logLevelFlag), "Log level")
pflag.Bool(leaderElectionFlag, viper.GetBool(leaderElectionFlag), "Enable leader election")
pflag.String(podNamespace, viper.GetString(podNamespace), "Pod namespace")
pflag.Duration(leaseDurationFlag, viper.GetDuration(leaseDurationFlag), "Leader election lease duration")
pflag.Duration(renewDeadlineFlag, viper.GetDuration(renewDeadlineFlag), "Leader election renew deadline")
pflag.Duration(retryPeriodFlag, viper.GetDuration(retryPeriodFlag), "Leader election retry period")
pflag.Parse()

viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.AutomaticEnv()
_ = viper.BindPFlags(pflag.CommandLine)

return processorConfig{
LogLevel: viper.GetString(logLevelFlag),
LeaderElection: viper.GetBool(leaderElectionFlag),
PodNamespace: viper.GetString(podNamespace),
LeaseDuration: viper.GetDuration(leaseDurationFlag),
RenewDeadline: viper.GetDuration(renewDeadlineFlag),
RetryPeriod: viper.GetDuration(retryPeriodFlag),
}
}

func main() {
ctx, cancelCtx := context.WithCancel(context.Background())
defer cancelCtx()

conf := parseEnvFlags()

logger.WithField("version", pkg.Version).WithField("processorConf", conf).
WithField("featureGates", runtime.EncodeFeatures()).
Info("Starting agones-processor")

logger.WithField("logLevel", conf.LogLevel).Info("Setting LogLevel configuration")
level, err := logrus.ParseLevel(strings.ToLower(conf.LogLevel))
if err == nil {
runtime.SetLevel(level)
} else {
logger.WithError(err).Info("Specified wrong Logging. Setting default loglevel - Info")
runtime.SetLevel(logrus.InfoLevel)
}

healthserver := &httpserver.Server{Logger: logger}
health := healthcheck.NewHandler()

config, err := rest.InClusterConfig()
if err != nil {
logger.WithError(err).Fatal("Failed to create in-cluster config")
panic("Failed to create in-cluster config: " + err.Error())
}
kubeClient, err := kubernetes.NewForConfig(config)
if err != nil {
logger.WithError(err).Fatal("Failed to create Kubernetes client")
panic("Failed to create Kubernetes client: " + err.Error())
}

go func() {
healthserver.Handle("/", health)
_ = healthserver.Run(context.Background(), 0)
}()

signals.NewSigTermHandler(func() {
logger.Info("Pod shutdown has been requested, failing readiness check")
cancelCtx()
os.Exit(0)
})

whenLeader(ctx, cancelCtx, logger, conf, kubeClient, func(ctx context.Context) {
logger.Info("Starting processor work as leader")

// Simulate processor work (to ensure the leader is working)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(non blocking suggestion)

Suggested change
// Simulate processor work (to ensure the leader is working)
// Simulate processor work (to ensure the leader is working)
// TODO: implement processor work

Just to make it extra clear that more work is coming.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated: a9b200f

// TODO: implement processor work
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()

for {
select {
case <-ctx.Done():
logger.Info("Processor work completed")
return
case <-ticker.C:
logger.Info("Processor is active as leader")
}
}
})

logger.Info("Processor exited gracefully.")
}

func whenLeader(ctx context.Context, cancel context.CancelFunc, logger *logrus.Entry,
conf processorConfig, kubeClient *kubernetes.Clientset, start func(_ context.Context)) {
if !conf.LeaderElection {
start(ctx)
return
}

id := uuid.New().String()

lock := &resourcelock.LeaseLock{
LeaseMeta: metav1.ObjectMeta{
Name: "agones-processor-lock",
Namespace: conf.PodNamespace,
},
Client: kubeClient.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: id,
},
}

logger.WithField("id", id).Info("Leader Election ID")

leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
// IMPORTANT: you MUST ensure that any code you have that
// is protected by the lease must terminate **before**
// you call cancel. Otherwise, you could have a background
// loop still running and another process could
// get elected before your background loop finished, violating
// the stated goal of the lease.
ReleaseOnCancel: true,
LeaseDuration: conf.LeaseDuration,
RenewDeadline: conf.RenewDeadline,
RetryPeriod: conf.RetryPeriod,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: start,
OnStoppedLeading: func() {
logger.WithField("id", id).Info("Leader Lost")
cancel()
os.Exit(0)
},
OnNewLeader: func(identity string) {
if identity == id {
return
}
logger.WithField("id", id).Info("New Leader Elected")
},
},
})
}
Loading