Skip to content

Commit

Permalink
add kube configs for timeline service
Browse files Browse the repository at this point in the history
  • Loading branch information
worstell committed Dec 5, 2024
1 parent 58f3b79 commit 9d2fe34
Show file tree
Hide file tree
Showing 16 changed files with 220 additions and 6 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ COPY . .
ENV PATH="$PATH:/root"

# Service-specific configurations
EXPOSE 8890
EXPOSE 8891
EXPOSE 8892
EXPOSE 8893
Expand Down
2 changes: 2 additions & 0 deletions backend/controller/admin/local_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func TestDiskSchemaRetrieverWithBuildArtefact(t *testing.T) {
in.WithFTLConfig("ftl-project-dr.toml"),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.CopyModule("dischema"),
in.Build("dischema"),
func(t testing.TB, ic in.TestContext) {
Expand All @@ -47,6 +48,7 @@ func TestDiskSchemaRetrieverWithNoSchema(t *testing.T) {
in.WithFTLConfig("ftl-project-dr.toml"),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.CopyModule("dischema"),
func(t testing.TB, ic in.TestContext) {
_, err := getDiskSchema(t, ic.Context)
Expand Down
1 change: 1 addition & 0 deletions backend/controller/encryption/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func TestKMSEncryptorLocalstack(ts *testing.T) {
in.WithLocalstack(),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.Action(func(t testing.TB, ic in.TestContext) {
endpoint := "http://localhost:4566"

Expand Down
1 change: 1 addition & 0 deletions backend/controller/sql/database_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func TestMigrate(t *testing.T) {
in.Run(t,
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.DropDBAction(t, dbName),
in.Fail(q(), "Should fail because the database does not exist."),
in.Exec("ftl", "migrate", "--dsn", dbUri),
Expand Down
7 changes: 6 additions & 1 deletion charts/ftl/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,9 @@ app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/name: {{ include "ftl.fullname" . }}
app.kubernetes.io/component: http-ingress
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- end -}}
{{- define "ftl-timeline.selectorLabels" -}}
app.kubernetes.io/name: {{ include "ftl.fullname" . }}
app.kubernetes.io/component: timeline
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
83 changes: 83 additions & 0 deletions charts/ftl/templates/timeline-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{{- if .Values.timeline.enabled }}
{{ $version := printf "v%s" .Chart.Version -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ftl.fullname" . }}-timeline
labels:
{{- include "ftl.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.timeline.replicas }}
revisionHistoryLimit: {{ .Values.timeline.revisionHistoryLimit }}
selector:
matchLabels:
{{- include "ftl-timeline.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "ftl-timeline.selectorLabels" . | nindent 8 }}
{{- if .Values.timeline.podAnnotations }}
annotations:
{{- toYaml .Values.timeline.podAnnotations | nindent 8 }}
{{- end }}
spec:
serviceAccountName: {{ .Values.timeline.serviceAccountName }}
containers:
- name: app
image: "{{ .Values.timeline.image.repository }}:{{ .Values.timeline.image.tag | default $version }}"
imagePullPolicy: {{ .Values.timeline.image.pullPolicy }}
resources:
limits:
cpu: "{{ .Values.timeline.resources.limits.cpu }}"
memory: "{{ .Values.timeline.resources.limits.memory }}"
requests:
cpu: "{{ .Values.timeline.resources.requests.cpu }}"
memory: "{{ .Values.timeline.resources.requests.memory }}"
{{- if .Values.timeline.envFrom }}
envFrom:
{{- if .Values.timeline.envFrom }}
{{- toYaml .Values.timeline.envFrom | nindent 12 }}
{{- end }}
{{- end }}
env:
{{- if .Values.timeline.env }}
{{- toYaml .Values.timeline.env | nindent 12 }}
{{- end }}

ports:
{{- range .Values.timeline.ports }}
- name: {{ .name }}
containerPort: {{ .containerPort }}
protocol: {{ .protocol | default "TCP" }}
{{- end }}
readinessProbe:
{{- if .Values.timeline.readinessProbe }}
{{- toYaml .Values.timeline.readinessProbe | nindent 12 }}
{{- else }}
httpGet:
path: /healthz
port: 8890
initialDelaySeconds: 1
periodSeconds: 2
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 15
{{- end }}
{{- if .Values.timeline.nodeSelector }}
nodeSelector:
{{- toYaml .Values.timeline.nodeSelector | nindent 8 }}
{{- end }}
{{- if .Values.timeline.affinity }}
affinity:
{{- toYaml .Values.timeline.affinity | nindent 8 }}
{{- end }}
{{- if .Values.timeline.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml .Values.timeline.topologySpreadConstraints | nindent 8 }}
{{- end }}
{{- if .Values.timeline.tolerations }}
tolerations:
{{- toYaml .Values.timeline.tolerations | nindent 8 }}
{{- end }}

{{- end }}
8 changes: 8 additions & 0 deletions charts/ftl/templates/timeline-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{- if .Values.timeline.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.timeline.serviceAccountName }}
namespace: {{ .Release.Namespace }}

{{- end }}
24 changes: 24 additions & 0 deletions charts/ftl/templates/timeline-services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{- if .Values.timeline.enabled }}
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "ftl.labels" . | nindent 4 }}
name: {{ include "ftl.fullname" . }}-timeline
{{- if .Values.timeline.service.annotations }}
annotations:
{{- toYaml .Values.timeline.service.annotations | nindent 4 }}
{{- end }}
spec:
ports:
{{- range .Values.timeline.service.ports }}
- name: {{ .name }}
port: {{ .port }}
protocol: {{ .protocol | default "TCP" }}
targetPort: {{ .targetPort }}
{{- end }}
selector:
{{- include "ftl-timeline.selectorLabels" . | nindent 4 }}
type: {{ .Values.timeline.service.type | default "ClusterIP" }}

{{- end }}
59 changes: 59 additions & 0 deletions charts/ftl/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,62 @@ ingress:
affinity: null
topologySpreadConstraints: null
tolerations: null

timeline:
enabled: true
env:
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: FTL_ENDPOINT
value: "http://ftl-controller:8892"
- name: FTL_BIND
value: "http://$(MY_POD_IP):8890"
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
ports:
- name: http
containerPort: 8890
protocol: TCP

ingressAnnotations:
kubernetes.io/ingress.class: nginx
replicas: 2
revisionHistoryLimit: 0

image:
repository: "ftl0/ftl-timeline"
pullPolicy: IfNotPresent

resources:
requests:
memory: 512Mi
cpu: 10m
limits:
memory: 512Mi
cpu: 2

envFrom: null
serviceAccountName: ftl-timeline

readinessProbe: null

service:
type: ClusterIP
annotations: null
ports:
- name: "http-8890"
port: 80
protocol: TCP
targetPort: 8890

podAnnotations:
proxy.istio.io/config: |
holdApplicationUntilProxyStarts: true
nodeSelector: null
affinity: null
topologySpreadConstraints: null
tolerations: null
2 changes: 2 additions & 0 deletions deployment/Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ full-deploy: build-all-images setup-istio-cluster
kubectl rollout restart deployment ftl-provisioner || true # if this exists already restart it to get the latest image
kubectl rollout restart deployment ftl-cron || true # if this exists already restart it to get the latest image
kubectl rollout restart deployment ftl-http-ingress || true # if this exists already restart it to get the latest image
kubectl rollout restart deployment ftl-timeline || true # if this exists already restart it to get the latest image
just apply || sleep 5 # wait for CRDs to be created, the initial apply will usually fail
just apply

Expand All @@ -37,6 +38,7 @@ wait-for-kube:
kubectl wait --for=condition=ready pod/ftl-postgresql-0 --timeout=5m
kubectl wait --for=condition=available deployment/ftl-controller --timeout=5m
kubectl wait --for=condition=available deployment/ftl-http-ingress --timeout=5m
kubectl wait --for=condition=available deployment/ftl-timeline --timeout=5m
kubectl wait --for=condition=available deployment/registry --timeout=5m
sleep 1
ftl status || sleep 5 && ftl status
Expand Down
5 changes: 3 additions & 2 deletions frontend/cli/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestConfigsWithController(t *testing.T) {
}

func TestConfigsWithoutController(t *testing.T) {
Run(t, configActions(t, WithoutController(), WithoutProvisioner())...)
Run(t, configActions(t, WithoutController(), WithoutProvisioner(), WithoutTimeline())...)
}

func configActions(t *testing.T, prepend ...ActionOrOption) []ActionOrOption {
Expand All @@ -44,7 +44,7 @@ func TestSecretsWithController(t *testing.T) {
}

func TestSecretsWithoutController(t *testing.T) {
Run(t, secretActions(t, WithoutController(), WithoutProvisioner())...)
Run(t, secretActions(t, WithoutController(), WithoutProvisioner(), WithoutTimeline())...)
}

func secretActions(t *testing.T, prepend ...ActionOrOption) []ActionOrOption {
Expand Down Expand Up @@ -97,6 +97,7 @@ func testImportExport(t *testing.T, object string) {
Run(t,
WithoutController(),
WithoutProvisioner(),
WithoutTimeline(),
// duplicate project file in the temp directory
Exec("cp", firstProjFile, secondProjFile),
// import into first project file
Expand Down
2 changes: 1 addition & 1 deletion frontend/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type InteractiveCLI struct {
Version kong.VersionFlag `help:"Show version."`
Endpoint *url.URL `default:"http://127.0.0.1:8892" help:"FTL endpoint to bind/connect to." env:"FTL_ENDPOINT"`
ProvisionerEndpoint *url.URL `help:"Provisioner endpoint." env:"FTL_PROVISIONER_ENDPOINT" default:"http://127.0.0.1:8893"`
TimelineEndpoint *url.URL `help:"Timeline endpoint." env:"FTL_TIMELINE_ENDPOINT" default:"http://127.0.0.1:8894"`
TimelineEndpoint *url.URL `help:"Timeline endpoint." env:"FTL_TIMELINE_ENDPOINT" default:"http://127.0.0.1:8890"`

Ping pingCmd `cmd:"" help:"Ping the FTL cluster."`
Status statusCmd `cmd:"" help:"Show FTL status."`
Expand Down
1 change: 1 addition & 0 deletions go-runtime/ftl/ftltest/ftltest_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func TestModuleUnitTests(t *testing.T) {
in.WithFTLConfig("wrapped/ftl-project.toml"),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.GitInit(),
in.CopyModule("time"),
in.CopyModule("wrapped"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func TestBuilds(t *testing.T) {
in.WithLanguages("go"),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.CopyModule(MODULE_NAME),
startPlugin(),
setUpModuleConfig(MODULE_NAME),
Expand Down Expand Up @@ -130,6 +131,7 @@ func TestDependenciesUpdate(t *testing.T) {
in.WithLanguages("go"), //no java support yet, as it relies on writeGenericSchemaFiles
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.CopyModule(MODULE_NAME),
startPlugin(),
setUpModuleConfig(MODULE_NAME),
Expand Down Expand Up @@ -165,6 +167,7 @@ func TestBuildLock(t *testing.T) {
in.WithLanguages("go"),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.CopyModule(MODULE_NAME),
startPlugin(),
setUpModuleConfig(MODULE_NAME),
Expand Down Expand Up @@ -194,6 +197,7 @@ func TestBuildsWhenAlreadyLocked(t *testing.T) {
in.WithLanguages("go"),
in.WithoutController(),
in.WithoutProvisioner(),
in.WithoutTimeline(),
in.CopyModule(MODULE_NAME),
startPlugin(),
setUpModuleConfig(MODULE_NAME),
Expand Down
24 changes: 22 additions & 2 deletions internal/integration/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ func WithoutProvisioner() Option {
}
}

// WithoutTimeline is a Run* option that disables starting the timeline service.
func WithoutTimeline() Option {
return func(o *options) {
o.startTimeline = false
}
}

// WithProvisionerConfig is a Run* option that specifies the provisioner config to use.
func WithProvisionerConfig(config string) Option {
return func(o *options) {
Expand All @@ -174,6 +181,7 @@ type options struct {
startController bool
devMode bool
startProvisioner bool
startTimeline bool
provisionerConfig string
requireJava bool
envars map[string]string
Expand All @@ -193,6 +201,7 @@ func run(t *testing.T, actionsOrOptions ...ActionOrOption) {
opts := options{
startController: true,
startProvisioner: true,
startTimeline: true,
languages: []string{"go"},
envars: map[string]string{},
}
Expand Down Expand Up @@ -330,11 +339,13 @@ func run(t *testing.T, actionsOrOptions ...ActionOrOption) {
controller = rpc.Dial(ftlv1connect.NewControllerServiceClient, "http://localhost:8892", log.Debug)
console = rpc.Dial(pbconsoleconnect.NewConsoleServiceClient, "http://localhost:8892", log.Debug)
schema = rpc.Dial(ftlv1connect.NewSchemaServiceClient, "http://localhost:8892", log.Debug)
timeline = rpc.Dial(timelinev1connect.NewTimelineServiceClient, "http://localhost:8890", log.Debug)
}
if opts.startProvisioner {
provisioner = rpc.Dial(provisionerconnect.NewProvisionerServiceClient, "http://localhost:8893", log.Debug)
}
if opts.startTimeline {
timeline = rpc.Dial(timelinev1connect.NewTimelineServiceClient, "http://localhost:8890", log.Debug)
}

testData := filepath.Join(cwd, "testdata", language)
if opts.testDataDir != "" {
Expand All @@ -360,7 +371,6 @@ func run(t *testing.T, actionsOrOptions ...ActionOrOption) {
ic.Controller = controller
ic.Schema = schema
ic.Console = console
ic.Timeline = timeline

Infof("Waiting for controller to be ready")
ic.AssertWithRetry(t, func(t testing.TB, ic TestContext) {
Expand All @@ -379,6 +389,16 @@ func run(t *testing.T, actionsOrOptions ...ActionOrOption) {
})
}

if opts.startTimeline {
ic.Timeline = timeline

Infof("Waiting for timeline to be ready")
ic.AssertWithRetry(t, func(t testing.TB, ic TestContext) {
_, err := ic.Timeline.Ping(ic, connect.NewRequest(&ftlv1.PingRequest{}))
assert.NoError(t, err)
})
}

Infof("Starting test")

for _, action := range actions {
Expand Down
Loading

0 comments on commit 9d2fe34

Please sign in to comment.