Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pkov2] agent RPC server #624

Merged
merged 22 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
23 changes: 23 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@
"args": [
"--zap-level=debug"
]
},
{
"name": "Agent",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "agent",
"args": [
"serve",
"-v=false",
"--workspace=${input:workdir}",
"-s=dev"
],
"env": {
"AWS_REGION": "us-west-1",
}
}
],
"inputs": [
{
"id": "workdir",
"description": "Please provide the Pulumi program directory",
"type": "promptString"
}
]
}
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,7 @@ version:
dep-tidy:
go mod tidy

.PHONY: build build-static codegen generate-crds install-crds generate-k8s test version dep-tidy build-image push-image push-image-latest deploy prep-spec
agent:
cd agent && $(MAKE) agent

.PHONY: build build-static codegen generate-crds install-crds generate-k8s test version dep-tidy build-image push-image push-image-latest deploy prep-spec agent
1 change: 1 addition & 0 deletions agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pulumi-kubernetes-agent
54 changes: 54 additions & 0 deletions agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Build the agent binary
FROM golang:1.22 AS builder
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
FROM golang:1.22 AS builder
FROM --platform=$BUILDPLATFORM golang:1.22 AS builder

This will build in a native image instead of an emulated one when cross-compiling.

ARG TARGETOS
ARG TARGETARCH

WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum

# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download

# Copy the go source
COPY main.go main.go
COPY cmd/ cmd/
COPY pkg/ pkg/
COPY version/ version/

# Build
# the GOARCH has not a default value to allow the binary be built according to the host where the command
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o agent main.go

# runtime image
FROM gcr.io/distroless/static-debian12:debug-nonroot

# RUN apt-get install tini

# install agent binary
WORKDIR /
COPY --from=builder /workspace/agent agent
# COPY init.sh /opt/pulumi-kubernetes-operator/init.sh

# The image is intended as a tool
# ENTRYPOINT ["tini", "--"]

# RUN useradd -m pulumi-kubernetes-agent
# RUN mkdir -p /home/pulumi-kubernetes-agent/.ssh \
# && touch /home/pulumi-kubernetes-agent/.ssh/known_hosts \
# && chmod 700 /home/pulumi-kubernetes-agent/.ssh \
# && chown -R pulumi-kubernetes-agent:pulumi-kubernetes-agent /home/pulumi-kubernetes-agent/.ssh

# USER pulumi-kubernetes-agent

# ENV XDG_CONFIG_HOME=/tmp/.config
# ENV XDG_CACHE_HOME=/tmp/.cache
# ENV XDG_CONFIG_CACHE=/tmp/.cache
# ENV GOCACHE=/tmp/.cache/go-build
# ENV GOPATH=/tmp/.cache/go

20 changes: 20 additions & 0 deletions agent/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
all: protoc agent

ensure:
go mod tidy

protoc:
@echo "Generating Go files"
cd pkg/proto && protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative *.proto

agent: protoc
@echo "Building agent"
go build -o pulumi-kubernetes-agent \
github.com/pulumi/pulumi-kubernetes-operator/agent

image: agent
docker build -t pulumi/pulumi-kubernetes-agent:latest .

.PHONY: agent protoc image

83 changes: 83 additions & 0 deletions agent/cmd/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright © 2024 Pulumi Corporation

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.
*/
package cmd

import (
"os"

"github.com/fluxcd/pkg/http/fetch"
"github.com/spf13/cobra"
"go.uber.org/zap"
)

const (
DefaultFluxRetries = 3
)

var (
TargetDir string
FluxUrl string
FluxDigest string
)

// initCmd represents the init command
var initCmd = &cobra.Command{
Use: "init",
Short: "Initialize a Pulumi workspace",
Long: `Initialize a working directory to contain project sources.

For Flux sources:
pulumi-kubernetes-agent init --flux-fetch-url URL
`,
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
log.Debugw("executing init command", "TargetDir", TargetDir)

err := os.MkdirAll(TargetDir, 0777)
if err != nil {
log.Errorw("fatal: unable to make target directory", zap.Error(err))
os.Exit(1)
}
log.Debugw("target directory created", "dir", TargetDir)

// fetch the configured flux source
if FluxUrl != "" {
// https://github.com/fluxcd/kustomize-controller/blob/a1a33f2adda783dd2a17234f5d8e84caca4e24e2/internal/controller/kustomization_controller.go#L328
fetcher := fetch.New(
fetch.WithRetries(DefaultFluxRetries),
fetch.WithHostnameOverwrite(os.Getenv("SOURCE_CONTROLLER_LOCALHOST")),
fetch.WithUntar())

log.Infow("flux source fetching", "url", FluxUrl, "digest", FluxDigest)
err := fetcher.FetchWithContext(ctx, FluxUrl, FluxDigest, TargetDir)
if err != nil {
log.Errorw("fatal: unable to fetch flux source", zap.Error(err))
os.Exit(2)
}
log.Infow("flux source fetched", "dir", TargetDir)
}
},
}

func init() {
rootCmd.AddCommand(initCmd)
initCmd.Flags().StringVarP(&TargetDir, "target-dir", "t", "", "The target directory to initialize")
initCmd.MarkFlagRequired("target-dir")

initCmd.Flags().StringVar(&FluxUrl, "flux-url", "", "Flux archive URL")
initCmd.Flags().StringVar(&FluxDigest, "flux-digest", "", "Flux digest")
initCmd.MarkFlagsRequiredTogether("flux-url", "flux-digest")
}
71 changes: 71 additions & 0 deletions agent/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright © 2024 Pulumi Corporation

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.
*/
package cmd

import (
"os"

"github.com/spf13/cobra"
"go.uber.org/zap"
)

var verbose bool

// a command-specific logger
var log *zap.SugaredLogger
Copy link
Contributor

Choose a reason for hiding this comment

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

Structured logging ❤️


// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "agent",
Short: "Pulumi Kubernetes Operator Agent",
Long: `Provides tooling and a gRPC service for the Pulumi Kubernetes Operator
to use to perform stack operations.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
var err error

// initialize the global logger
zc := zap.NewDevelopmentConfig()
zc.DisableCaller = true
if !verbose {
zc.Level.SetLevel(zap.InfoLevel)
}
zapLog, err := zc.Build()
if err != nil {
return err
}
zap.ReplaceGlobals(zapLog)

// initialize a command-specific logger
log = zap.L().Named("cmd").Named(cmd.Name()).Sugar()
return nil
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return zap.L().Sync()
},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose logging")
}
Loading