Skip to content

Commit 96fa815

Browse files
committed
Update counter demo with external volume using mock volume plugin.
It makes the file counter path configurable so we can test it against different volume types. And adds an optional file verification step to test the presence of a file on an existing volume.
1 parent e2c56d1 commit 96fa815

3 files changed

Lines changed: 102 additions & 9 deletions

File tree

demos/counter/counter.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"net"
2828
"net/http"
2929
"os"
30+
"path/filepath"
3031
"strconv"
3132
"sync"
3233
"sync/atomic"
@@ -41,27 +42,27 @@ var (
4142
fileMutex sync.Mutex
4243
)
4344

44-
const fileCounterPath = "/home/counter/a.txt"
45-
46-
func incrementFileCounter() int {
45+
func incrementFileCounter(filePath string) int {
4746
fileMutex.Lock()
4847
defer fileMutex.Unlock()
4948
counter := 0
50-
data, err := os.ReadFile(fileCounterPath)
49+
data, err := os.ReadFile(filePath)
5150
if err == nil {
5251
if i, err := strconv.Atoi(string(data)); err == nil {
5352
counter = i
5453
}
5554
}
5655
counter++
57-
err = os.WriteFile(fileCounterPath, []byte(strconv.Itoa(counter)), 0o644)
56+
err = os.WriteFile(filePath, []byte(strconv.Itoa(counter)), 0o644)
5857
if err != nil {
5958
return -1
6059
}
6160
return counter
6261
}
6362

6463
func main() {
64+
fileCounterDirectory := pflag.String("file-counter-directory", "/home/counter", "Directory for file counter")
65+
validateExistingFilePath := pflag.String("validate-existing-file-path", "", "Path to existing file to validate reading")
6566
pflag.Parse()
6667
ctx := context.Background()
6768

@@ -70,11 +71,23 @@ func main() {
7071
defaultMux := http.NewServeMux()
7172
defaultMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
7273
ctx := r.Context()
73-
fileCounter := incrementFileCounter()
74-
74+
fileCounter := incrementFileCounter(filepath.Join(*fileCounterDirectory, "a.txt"))
7575
memoryCounter := atomic.AddUint64(&requestCount, 1)
7676
currentIP := getCurrentIP()
77-
response := fmt.Sprintf("hello from: %s | preserved memory count: %d | preserved file counter: %d\n", currentIP, memoryCounter, fileCounter)
77+
78+
fileContentStr := ""
79+
if *validateExistingFilePath != "" {
80+
fileContent, err := os.ReadFile(*validateExistingFilePath)
81+
if err != nil {
82+
fileResponse := fmt.Sprintf("failed to read test file: %s\n", err.Error())
83+
w.WriteHeader(http.StatusOK)
84+
w.Write([]byte(fileResponse))
85+
return
86+
}
87+
fileContentStr = fmt.Sprintf(" | file content: %s", string(fileContent))
88+
}
89+
90+
response := fmt.Sprintf("hello from: %s | preserved memory count: %d | preserved file counter: %d%s\n", currentIP, memoryCounter, fileCounter, fileContentStr)
7891
slog.InfoContext(ctx, "Handled request", slog.String("response", response))
7992

8093
w.WriteHeader(http.StatusOK)

demos/counter/counter.yaml.tmpl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,16 @@ spec:
4242
containers:
4343
- name: counter
4444
image: ko://github.com/agent-substrate/substrate/demos/counter
45-
command: ["/ko-app/counter"]
45+
command: ["/ko-app/counter", "--file-counter-directory=/home/counter", "--validate-existing-file-path=/external-data/test.txt"]
4646
readyz:
4747
httpGet:
4848
path: /readyz
4949
port: 80
5050
volumeMounts:
5151
- name: data
5252
mountPath: /home/counter
53+
- name: external-data
54+
mountPath: /external-data
5355
workerSelector:
5456
matchLabels:
5557
workload: counter
@@ -60,3 +62,7 @@ spec:
6062
volumes:
6163
- name: data
6264
durableDir: {}
65+
- name: external-data
66+
externalVolumeTemplate:
67+
capacity: 1Gi
68+
storageClassName: standard

hack/run-demo-counter-kind.sh

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2026 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -o errexit -o nounset -o pipefail
18+
19+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
20+
cd "${ROOT}"
21+
22+
# ANSI color codes for pretty output
23+
COLOR_CYAN='\033[1;36m'
24+
COLOR_GREEN='\033[1;32m'
25+
COLOR_YELLOW='\033[1;33m'
26+
COLOR_RED='\033[1;31m'
27+
COLOR_RESET='\033[0m'
28+
29+
function log_step() {
30+
echo -e "${COLOR_CYAN}[step]: $1${COLOR_RESET}"
31+
}
32+
33+
function log_success() {
34+
echo -e "${COLOR_GREEN}[success]: $1${COLOR_RESET}"
35+
}
36+
37+
function log_warn() {
38+
echo -e "${COLOR_YELLOW}[warning]: $1${COLOR_RESET}"
39+
}
40+
41+
function log_error() {
42+
echo -e "${COLOR_RED}[error]: $1${COLOR_RESET}"
43+
}
44+
45+
log_step "Cleaning up previous test"
46+
./hack/delete-kind-cluster.sh || true
47+
48+
log_step "Installing kind cluster"
49+
./hack/create-kind-cluster.sh
50+
51+
log_step "Installing ATE control plane, Valkey, and RustFS..."
52+
./hack/install-ate-kind.sh --deploy-ate-system
53+
54+
log_step "Installing counter demo..."
55+
./hack/install-ate-kind.sh --deploy-demo-counter
56+
57+
log_step "Installing kubectl-ate CLI..."
58+
go install ./cmd/kubectl-ate
59+
60+
log_step "Creating atespace (demo)..."
61+
kubectl ate create atespace demo
62+
63+
log_step "Creating counter actor (my-counter-1)..."
64+
kubectl ate create actor my-counter-1 --template ate-demo-counter/counter --atespace demo
65+
66+
log_success "Counter actor my-counter-1 created"
67+
echo ""
68+
echo -e "${COLOR_YELLOW}========================================================================${COLOR_RESET}"
69+
echo -e "To interact with the counter actor, open a separate terminal and run:"
70+
echo -e " curl -X POST -H \"Host: my-counter-1.demo.actors.resources.substrate.ate.dev\" -i http://localhost:8000/"
71+
echo -e "${COLOR_YELLOW}========================================================================${COLOR_RESET}"
72+
echo ""
73+
log_step "Starting port-forwarding for the network router (press Ctrl+C to stop)..."
74+
kubectl port-forward -n ate-system svc/atenet-router 8000:80

0 commit comments

Comments
 (0)