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

Unregister stateless agents from server on termination #2606

Merged
merged 4 commits into from
Nov 1, 2023
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
5 changes: 5 additions & 0 deletions agent/rpc/client_grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ func (c *client) RegisterAgent(ctx context.Context, platform, backend, version s
return res.GetAgentId(), err
}

func (c *client) UnregisterAgent(ctx context.Context) error {
_, err := c.client.UnregisterAgent(ctx, &proto.Empty{})
return err
}

func (c *client) ReportHealth(ctx context.Context) (err error) {
retry := c.newBackOff()
req := new(proto.ReportHealthRequest)
Expand Down
21 changes: 19 additions & 2 deletions cmd/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,20 @@
context.Background(),
metadata.Pairs("hostname", hostname),
)

agentConfigPersisted := abool.New()

Check warning on line 122 in cmd/agent/agent.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/agent.go#L121-L122

Added lines #L121 - L122 were not covered by tests
ctx = utils.WithContextSigtermCallback(ctx, func() {
println("ctrl+c received, terminating process")
log.Info().Msg("Termination signal is received, shutting down")

Check warning on line 124 in cmd/agent/agent.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/agent.go#L124

Added line #L124 was not covered by tests
sigterm.Set()

// Remove stateless agents from server
if agentConfigPersisted.IsNotSet() {
log.Debug().Msg("Unregistering agent from server")
err := client.UnregisterAgent(ctx)
if err != nil {
log.Err(err).Msg("Failed to unregister agent from server")
}

Check warning on line 133 in cmd/agent/agent.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/agent.go#L126-L133

Added lines #L126 - L133 were not covered by tests
}
})

// check if grpc server version is compatible with agent
Expand Down Expand Up @@ -165,7 +176,11 @@
return err
}

writeAgentConfig(agentConfig, agentConfigPath)
if agentConfigPath != "" {
if err := writeAgentConfig(agentConfig, agentConfigPath); err == nil {
agentConfigPersisted.Set()
}

Check warning on line 182 in cmd/agent/agent.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/agent.go#L179-L182

Added lines #L179 - L182 were not covered by tests
}

labels := map[string]string{
"hostname": hostname,
Expand All @@ -187,6 +202,7 @@
go func() {
for {
if sigterm.IsSet() {
log.Debug().Msg("Terminating health reporting")

Check warning on line 205 in cmd/agent/agent.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/agent.go#L205

Added line #L205 was not covered by tests
return
}

Expand All @@ -210,6 +226,7 @@

for {
if sigterm.IsSet() {
log.Debug().Msgf("terminating runner %d", i)

Check warning on line 229 in cmd/agent/agent.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/agent.go#L229

Added line #L229 was not covered by tests
return
}

Expand Down
11 changes: 9 additions & 2 deletions cmd/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
AgentID: defaultAgentIDValue,
}

if agentConfigPath == "" {
return conf
}

Check warning on line 40 in cmd/agent/config.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/config.go#L39-L40

Added lines #L39 - L40 were not covered by tests

rawAgentConf, err := os.ReadFile(agentConfigPath)
if err != nil {
if os.IsNotExist(err) {
Expand All @@ -54,11 +58,11 @@
return conf
}

func writeAgentConfig(conf AgentConfig, agentConfigPath string) {
func writeAgentConfig(conf AgentConfig, agentConfigPath string) error {
rawAgentConf, err := json.Marshal(conf)
if err != nil {
log.Error().Err(err).Msg("could not marshal agent config")
return
return err

Check warning on line 65 in cmd/agent/config.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/config.go#L65

Added line #L65 was not covered by tests
}

// get old config
Expand All @@ -68,6 +72,9 @@
if !bytes.Equal(rawAgentConf, oldRawAgentConf) {
if err := os.WriteFile(agentConfigPath, rawAgentConf, 0o644); err != nil {
log.Error().Err(err).Msgf("could not persist agent config at '%s'", agentConfigPath)
return err

Check warning on line 75 in cmd/agent/config.go

View check run for this annotation

Codecov / codecov/patch

cmd/agent/config.go#L75

Added line #L75 was not covered by tests
}
}

return nil
}
4 changes: 2 additions & 2 deletions cmd/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestReadAgentIDFileExists(t *testing.T) {

// update existing config and check
actual.AgentID = 33
writeAgentConfig(actual, tmpF.Name())
_ = writeAgentConfig(actual, tmpF.Name())
actual = readAgentConfig(tmpF.Name())
assert.EqualValues(t, 33, actual.AgentID)

Expand All @@ -55,7 +55,7 @@ func TestReadAgentIDFileExists(t *testing.T) {
defer os.Remove(tmpF2.Name())

// write new config
writeAgentConfig(actual, tmpF2.Name())
_ = writeAgentConfig(actual, tmpF2.Name())
actual = readAgentConfig(tmpF2.Name())
assert.EqualValues(t, 33, actual.AgentID)
}
2 changes: 1 addition & 1 deletion cmd/agent/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var flags = []cli.Flag{
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_AGENT_CONFIG_FILE"},
Name: "agent-config",
Usage: "agent config file path",
Usage: "agent config file path, if set empty the agent will be stateless and unregister on termination",
Value: "/etc/woodpecker/agent.conf",
},
&cli.StringSliceFlag{
Expand Down
6 changes: 5 additions & 1 deletion pipeline/backend/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
)

const (
EngineName = "kubernetes"
)

var noContext = context.Background()

type kube struct {
Expand Down Expand Up @@ -98,7 +102,7 @@
}

func (e *kube) Name() string {
return "kubernetes"
return EngineName

Check warning on line 105 in pipeline/backend/kubernetes/kubernetes.go

View check run for this annotation

Codecov / codecov/patch

pipeline/backend/kubernetes/kubernetes.go#L105

Added line #L105 was not covered by tests
}

func (e *kube) IsAvailable(context.Context) bool {
Expand Down
3 changes: 3 additions & 0 deletions pipeline/rpc/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ type Peer interface {
// RegisterAgent register our agent to the server
RegisterAgent(ctx context.Context, platform, backend, version string, capacity int) (int64, error)

// UnregisterAgent unregister our agent from the server
UnregisterAgent(ctx context.Context) error

// ReportHealth reports health status of the agent to the server
ReportHealth(c context.Context) error
}
2 changes: 1 addition & 1 deletion pipeline/rpc/proto/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ package proto

// Version is the version of the woodpecker.proto file,
// !IMPORTANT! increased by 1 each time it get changed !IMPORTANT!
const Version int32 = 4
const Version int32 = 5
65 changes: 35 additions & 30 deletions pipeline/rpc/proto/woodpecker.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 11 additions & 10 deletions pipeline/rpc/proto/woodpecker.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ package proto;

// Woodpecker Server Service
service Woodpecker {
rpc Version (Empty) returns (VersionResponse) {}
rpc Next (NextRequest) returns (NextResponse) {}
rpc Init (InitRequest) returns (Empty) {}
rpc Wait (WaitRequest) returns (Empty) {}
rpc Done (DoneRequest) returns (Empty) {}
rpc Extend (ExtendRequest) returns (Empty) {}
rpc Update (UpdateRequest) returns (Empty) {}
rpc Log (LogRequest) returns (Empty) {}
rpc RegisterAgent (RegisterAgentRequest) returns (RegisterAgentResponse) {}
rpc ReportHealth (ReportHealthRequest) returns (Empty) {}
rpc Version (Empty) returns (VersionResponse) {}
rpc Next (NextRequest) returns (NextResponse) {}
rpc Init (InitRequest) returns (Empty) {}
rpc Wait (WaitRequest) returns (Empty) {}
rpc Done (DoneRequest) returns (Empty) {}
rpc Extend (ExtendRequest) returns (Empty) {}
rpc Update (UpdateRequest) returns (Empty) {}
rpc Log (LogRequest) returns (Empty) {}
rpc RegisterAgent (RegisterAgentRequest) returns (RegisterAgentResponse) {}
rpc UnregisterAgent (Empty) returns (Empty) {}
rpc ReportHealth (ReportHealthRequest) returns (Empty) {}
}

//
Expand Down
59 changes: 48 additions & 11 deletions pipeline/rpc/proto/woodpecker_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading