Skip to content

[cmd/opampsupervisor]: Implement PackagesAvailable for upgrading agent#35503

Closed
BinaryFissionGames wants to merge 1 commit into
open-telemetry:mainfrom
observIQ:feat/supervisor-update-collector
Closed

[cmd/opampsupervisor]: Implement PackagesAvailable for upgrading agent#35503
BinaryFissionGames wants to merge 1 commit into
open-telemetry:mainfrom
observIQ:feat/supervisor-update-collector

Conversation

@BinaryFissionGames

Copy link
Copy Markdown
Contributor

Description:
Implements ReportPackageStatuses and taking PackagesAvailable for upgrading the agent.

The agent will only accept a top-level package with an empty name. This agent must be signed using cosign's keyless signing method (this is how the opentelemetry-collector-releases repository signs its releases).

The signature field must be populated with the resultant base64 encoded cert and signature, both being space separated (signature = b64_cert + " " + b64_signature).

This first implementation only allows online verification; In order to verify the certificate, it must reach out to the public rekor transparency log instance. It also fetches certificates from the internet. Some of these things are configurable through environment variables, but I figure we can parse out how offline signature verification works in a follow-up PR. This basic setup should allow for signature verification for agents that have access to the internet.

This PR also does not revert the collector if it is unhealthy. This will need to be done in a follow up PR. I think we should do it after #34907 is merged, as I imagine the logic will overlap here.

Link to tracking Issue: Closes #34734, Partially solves #33947

Testing:

  • Unit testing, e2e testing

@BinaryFissionGames
BinaryFissionGames marked this pull request as ready for review October 1, 2024 08:07
@BinaryFissionGames
BinaryFissionGames requested a review from a team as a code owner October 1, 2024 08:07

@evan-bradley evan-bradley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for taking this on, its no small task. I'm still looking through this, but wanted to give early feedback on a few points.

Comment thread cmd/opampsupervisor/e2e_test.go Outdated
return nil
}

// TODO: Certificate paths? The certificate can be specified via SIGSTORE_ROOT_FILE for now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we link to an issue here? It would make it easier to track and provides some context.

agentHash := h.Sum(nil)

// Load persisted package state, if it exists
// TODO: use packagesStatusPath method somehow

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is okay given that it's the only other usage of this and is a very simple call to filepath.Join.

The other options I can think of aren't worth the additional complexity:

  1. Extract the packagesStatusPath functionality to a function and call the function in the method as well. Too much abstraction for a simple call.
  2. Instantiate packageManager above and call pathagesStatusPath here, then fill in other details on the struct afterward. Splits the initialization too much for fairly minimal gains.

return err
}

type packageState struct {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would it make sense to instead use the persistent state file to store this? I see how the purpose of each file is distinct, but having two small-ish YAML files also feels a little odd.

This may also be premature, but I think abstracting state storage through the persistent state struct may keep things cleaner in the long run.

// shuts down the Collector. This only needs to happen
// once per Collector binary.
func (s *Supervisor) getBootstrapInfo() (err error) {
func (s *Supervisor) getBootstrapInfo() (agentVersion string, err error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is another place where consolidating our storage to the persistent state may make things cleaner. We have two different data flows for the instance ID vs. the agent version in this function, when I think we should probably store the two next two each other so all of the agent's information is recorded in the same place. What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Can you clarify on what's being proposed here? I don't think we should store the agent version anywhere, we should always treat the reported version from the agent as the source of truth (as best we can, anyways).

}

// overwrite agent process
startAgent, err := p.am.stopAgentProcess(ctx)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do you think it would substantially complicate things if we limited agent process management to the Supervisor struct and only deal with managing the binary file here? My first impression is that we should keep those responsibilities separated if possible and not have the package manager know anything about the Collector process, even if the current implementation isn't too complicated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My thought was that we need to stop the agent process to write the binary in the first place.

We could write the binary somewhere temporarily, and send a message to the agent goroutine to do the replacement, which could be cleaner (better separation of concerns). The package manager would still need to have some handle to signal that, but it wouldn't necessarily be tied to the collector.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would we be able to accomplish this with synchronous, one-way communication? I was thinking maybe we could do something vaguely like this in the Supervisor struct:

oldVersion := 0
newVersion := 1

s.commander.stopAgent()
s.packageManager.SwapInVersion(newVersion)

if err := s.commander.startAgent(); err != nil {
	s.packageManager.SwapInVersion(oldVersion)
	s.commander.startAgent()
	s.reportFailedInstallation()
	return
}

s.packageManager.DeleteVersion(oldVersion)
s.reportSuccessfulInstallation()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I think we could do something like that. I think this also sets us up nicely for restoring the previous version if the new one fails. I'll look into making those changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Alright, so I'm looking a bit deeper and the reason I'm a little iffy on this is because it seems like there will be some odd consequences with doing this outside of the package syncer.

Essentially, the package syncer will run it's logic, then it will report the status off every package at the end. So it's possible that the package downloads and verifies fine, so the package syncer reports the package as installed - but then there is an error when swapping in the version, which causes an error.

I would prefer if we didn't report the package is installed before it's actually successfully installed, basically. Which means we'd have to do it in the package manager during the UpdateContent call, as far as I can tell. This would require 2 way communication, one way from (packagemanager) -> (agent goroutine) to do the swap, then one from (agent goroutine) -> (package manager) to indicate success/failure.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If PackageSyncer's design and API makes this difficult we should feel free to redesign it. Please don't feel constrained by it. This was the most basic design I could come up with when implementing the example and there may very well be a better design. Feel free to suggest one.

if err != nil {
s.logger.Error("Failed to sync PackagesAvailable message", zap.Error(err))
}
// TODO: Should we wait for the sync to be done somehow? Should it be in a separate goroutine

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From what I'm seeing, the Done channel only communicates that the PackageSyncer is done communicating package statuses to the server, and doesn't track whether the packages have been downloaded: https://github.com/open-telemetry/opamp-go/blob/main/client/internal/packagessyncer.go#L51. It may be worth waiting for this before communicating any additional updates about package statuses to the server.

@BinaryFissionGames BinaryFissionGames Oct 4, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm actually really confused reading that code. It looks like once Sync is done, that channel is closed, so waiting on Done here wouldn't actually add any extra synchronization.

Good call at looking at that impl, I definitely had a different idea of its purpose in my head.

@evan-bradley

Copy link
Copy Markdown
Member

@tigrannajaryan I'd appreciate you taking a look at this, even if just to review conformance to the spec.

@tigrannajaryan tigrannajaryan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I started reviewing but got confused by the many moving parts of signatures and verifications.

I think we need a design doc or some other form of documentation that explains all the involved parties (cosign, Collector releases, OpAMP Server, Supervisor) and how they dance together to make sure the downloaded binary is what it pretends to be and is safe to use.

Some sort of a sequence diagram that starts with the Collector build on opentelemetry-collector-releases and ends with Supervisor launching the new executable and shows all the steps in between would be great. If we number the steps we could even refer to them in the code.

}

// TODO: Certificate paths? The certificate can be specified via SIGSTORE_ROOT_FILE for now
type AgentSignature struct {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please document AgentSignature and AgentSignatureIdentity.

return splitSignature[0], splitSignature[1], nil
}

// sig is the decoded signature of

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incomplete comment?

}

func parsePackageSignature(signature []byte) (b64Cert, b64Signature []byte, err error) {
splitSignature := bytes.SplitN(signature, []byte(" "), 2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this signature format documented somewhere? This imposes a requirement on the OpAMP server to generate signatures in a specific way, right?

@BinaryFissionGames

Copy link
Copy Markdown
Contributor Author

I think we need a design doc or some other form of documentation that explains all the involved parties (cosign, Collector releases, OpAMP Server, Supervisor) and how they dance together to make sure the downloaded binary is what it pretends to be and is safe to use.

Yeah, good call out. I will work on this and get something in our spec that explains everything here.

by the OpAMP Server, if the AcceptsPackages capability is enabled.

### Overview
![Supervisor architecture diagram](agent-upgrades-e2e.png)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Excellent diagram and workflow description! Thank you. This is very heplful.

the URL that the OpAMP server gave it for downloading. After
downloading, it verifies the content hash matches the server
provided content hash from the PackagesAvailable message.
9. The supervisor verifies the certificate via the root certificates downloaded in step 7.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you clarify what is the difference between "verifies the certificate via the root certificates" and checks against the Rekor transparency log to verify the certificate hasn't been tampered with". I assume certificate is signed by a root certificate (the CA), so if it was tampered it would not pass the first verification step. How is possible that it passes the first check but fails the second? Are we thinking about a scenario that the root certificate is tampered with?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm actually a little iffy on this myself. I think the transparency log is related to the time of signing in some way, I'll dig a little more to see if I can understand better.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From what I can understand:

  1. Release flow requests to sign something with a given OIDC identity through Cosign.
  2. Cosign requests a signing certificate from Fulcio based on this OIDC identity.
  3. Fulcio then verifies the identity, generates and signs the short-lived cert/pub-key pair for Cosign.
  4. Fulcio delivers the cert/pub-key pair to Cosign
  5. Cosign then uses the pub-key to sign the released binaries.
  6. Cosign stores in Rekor: the cert, the pub-key, the sha of the binary that was signed.

Now, the verification happens:

  1. Supervisor sees a binary with a certificate, a signature, and it says "I want to verify that this package was built by this (could be an email address), at , and the issuer of the identity is ".
  2. Fulcio has a record of which certificates were issued to who and when... it is a CA after all.
  3. Supervisor verifies that the pub key from that signing cert generated the provided signature of the binary.
  4. Supervisor verifies with Fulcio's root cert that the signing certificate it got is valid and came from Fulcio.
  5. But who can guarantee to the Supervisor that the signing certificate from Fulcio was really signed by that OIDC identity? What if somebody other than Cosign requested that cert directly to Fulcio? Did they really verify control of the OIDC identity? That's why Rekor exists. It's basically a WAL of what Cosign did. So the Supervisor can then verify that record that Cosign created by double-checking in it: the sha of the binary, the signature, and the public key.

Comment thread cmd/opampsupervisor/specification/README.md Outdated
* This field may be explicitly set empty to skip verifying the repository field
in the certificate
* A set of [Fulcio] root certificates.
* These certificates are retrieved from "https://tuf-repo-cdn.sigstore.dev"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be interesting to explore the possibility of offline certificate verification. We could embed the root certificates in the Supervisor at build time, but I don't know if the verification process itself can be done without connecting to Rekor.
This can be a future work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

there is an option to skip the Rekor/transparency log verification. I couldn't get it to work as I was developing, but I figure it's probably something simple I was missing. We should definitely be able to get it working in some follow-up.

@dpaasman00
dpaasman00 force-pushed the feat/supervisor-update-collector branch 2 times, most recently from c535e23 to f7d67cc Compare October 31, 2024 15:20
@tigrannajaryan

Copy link
Copy Markdown
Member

@andykellr or @dpaasman00 do you plan to take over this PR?

@dpaasman00

Copy link
Copy Markdown
Contributor

@tigrannajaryan Yes, I will be taking this PR over!

@dpaasman00
dpaasman00 force-pushed the feat/supervisor-update-collector branch 2 times, most recently from 7e25bbb to 3750f52 Compare November 8, 2024 15:43
@dpaasman00

Copy link
Copy Markdown
Contributor

@evan-bradley @tigrannajaryan Are you able to take another look when you have a chance? I believe feedback you left for Brandon was addressed, so let me know if there's anything that was missed!

type AgentSignature struct {
// TODO: The Fulcio root certificate can be specified via SIGSTORE_ROOT_FILE for now
// But we should add it as a config option.
// https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/3593

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wrong link?

Comment thread cmd/opampsupervisor/supervisor/config/config.go Outdated
Comment on lines +224 to +231
// github_workflow_repository defines the expected repository field
// on the sigstore certificate.
CertGithubWorkflowRepository string `mapstructure:"github_workflow_repository"`

// Identities is a list of valid identities to use when verifying the agent.
// Only one needs to match the identity on the certificate for signature
// verification to pass.
Identities []AgentSignatureIdentity `mapstructure:"identities"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is the reason that these need to be configurable? Is it so that non-official Collector builds can be supported?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yea

Comment thread cmd/opampsupervisor/supervisor/packages.go Outdated
topLevelVersion string

storageDir string
agentPath string

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this the executable file path or a directory path where executable is contained? Perhaps agentExePath or agentFilePath to make it clear?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's the executable, so renaming to agentExePath

}

// Create reader for new agent
gzipReader, err := gzip.NewReader(bytes.NewBuffer(by))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we know the content is gzip? Is this specified somewhere?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This isn't strictly specified anywhere, but I think the idea is the releases repo where the signatures and binaries are stored have all collector binaries available as gzip artifacts, ignoring the different package installations that are posted there too.

return fmt.Errorf("read tarball for collector: %w", err)
}

for h.Name != "otelcol-contrib" {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How do we know the part name is "otelcol-contrib"? It would nice to document this and the fact that it is gziped tarball.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Similar to the gzip thing, this is based on the way the releases repo formats the collector releases. The collector binary in the gzip is titled "otelcol-contrib".

I can add documentation around these things. What do you think about making this part name configurable?

@douglascamata douglascamata Jun 4, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We are already making a big enough assumption that packages will be always in a gzip archive, so I think we can also assume the archive should contain only the Collector binary and nothing else, so we don't need to care about the name?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, my proposal is only valid for updates of the top-level package. 😅

defer agentFile.Close()

// Copy to backup
_, err = io.Copy(backupFile, agentFile)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A possible alternate instead of copying the files is to rename them. Delete backup, rename original to backup, write to the original name. Skips the copying and is likely faster.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sounds good, I'll implement this change

}
defer restoreFile.Close()

if _, err := io.Copy(restoreFile, backupFile); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to keep the backup file or we can rename instead of copying? Renaming likely is less susceptible to out-of-disk-space issues.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Implemented this similar to the process of backing up


return &packageManager{
persistentState: persistentState,
topLevelHash: agentHash,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is a bit confusing that we have both AllPackagesHash and topLevelHash. Are they the same or different? If different it would be nice to explain in a comment somewhere.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I added some comments to try and reduce the confusion. Technically they are different. The AllPackagesHash is a combination of all the hashes of the packages this package manager manages. topLevelHash is the hash for the collector package. Technically they are different, but right now in practice they should be the same because we're only managing the collector package.

@tigrannajaryan

Copy link
Copy Markdown
Member

I am most concerned about the hash/signature verification parts. We want to make sure we don't have any vulnerabilities here and don't introduce any in the future.

I think it is important that we have good test coverage for the verification code. Would you be able to add some tests? I can't see coverage results for this PR in codecov. Ideally we want to have full branch coverage for UpdateContent and funcs it calls.

@tigrannajaryan

Copy link
Copy Markdown
Member

@dpaasman00 ping me when you want me to do another round.

@github-actions

github-actions Bot commented Dec 3, 2024

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@dpaasman00

Copy link
Copy Markdown
Contributor

Planning to get back and address review by the end of the next week, December 13.

@github-actions

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions github-actions Bot added the Stale label Dec 18, 2024
@github-actions github-actions Bot removed the Stale label Aug 8, 2025
@dpaasman00
dpaasman00 force-pushed the feat/supervisor-update-collector branch 4 times, most recently from 8163a64 to 7403c98 Compare August 12, 2025 19:13
@dpaasman00

dpaasman00 commented Aug 12, 2025

Copy link
Copy Markdown
Contributor

The e2e test will continue failing until this PR in OpAmp-Go is included.

return

case stopRequest := <-s.agentStopChan:
err := s.commander.Stop(context.Background())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this select case could result in a hung supervisor in some circumstances.

When commander.Stop is called, it blocks until the agent process has terminated. If the agent process does not terminate promptly, the supervisor will wait a little bit of time before issuing SIGKILL to the agent process. However, whether or not the process actually reliably terminates after this SIGKILL is OS-dependent and situation-dependent.

It's a rare circumstance, but processes can get into states where they don't respond to SIGKILL. For a Linux-specific example of one way this can happen: https://chrisdown.name/2024/02/05/reliably-creating-d-state-processes-on-demand.html

When systemd encounters a process that doesn't terminate on SIGKILL after a timeout, it marks the unit as failed and moves on with its other duties. However it's not completely clear what the opamp supervisor should do, since it only supervises one thing. My instinct is that it should probably crash after a further timeout.

In any case, I think that this condition should be detected by the supervisor and handled in some way, perhaps in the commander package for the sake of abstraction.

@dpaasman00
dpaasman00 force-pushed the feat/supervisor-update-collector branch 3 times, most recently from 61f48c0 to 8b37fa1 Compare August 18, 2025 18:24
Comment on lines +252 to +263
// 7. Overwrite the existing agent file with the new agent.
if err = renameFile(tmpFilePath, p.agentExePath); err != nil {
if restoreErr := renameFile(agentBackupPath, p.agentExePath); restoreErr != nil {
return errors.Join(fmt.Errorf("rename tmp file to agent executable path: %w", err), fmt.Errorf("restore agent backup: %w", restoreErr))
}
return fmt.Errorf("successfully restored backup, but failed to rename tmp file to agent executable path: %w", err)
}

// 8. Delete the backup after a successful update.
if err = os.Remove(agentBackupPath); err != nil {
return fmt.Errorf("delete agent backup: %w", err)
}

@OrangeFlag OrangeFlag Aug 18, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Before removing the backup, consider starting/health-checking the agent. We might also want to keep the backup instead of deleting it immediately -- e.g., retain it for a grace period (TTL) and delete only after the agent has been healthy for N minutes or after the next successful update, so we preserve a quick rollback path if an intermittent/latent bug surfaces.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Great point, @OrangeFlag. I'm +1 to this.

@github-actions

github-actions Bot commented Sep 3, 2025

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions github-actions Bot added the Stale label Sep 3, 2025
@dpaasman00
dpaasman00 force-pushed the feat/supervisor-update-collector branch from 8b37fa1 to 35c7388 Compare September 11, 2025 15:34
@dpaasman00

Copy link
Copy Markdown
Contributor

New issue in OpAMP Go, this time related to setting the capabilities needed for upgrades. Have an issue opened here: open-telemetry/opamp-go#448

@github-actions

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@hdilip-pub

Copy link
Copy Markdown

Hi, I found a bug where the supervisor writes the temporary bootstrap port to effective.yaml instead of the main supervisor port, causing the agent to become unhealthy after a binary upgrade (as it is unable to connect to the supervisor). I've opened a PR with a fix.

@atoulme

atoulme commented Nov 20, 2025

Copy link
Copy Markdown
Contributor

Please fix conflicts and mark ready to review again.

@github-actions

github-actions Bot commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

3 similar comments
@github-actions

github-actions Bot commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@github-actions

Copy link
Copy Markdown
Contributor

Closed as inactive. Feel free to reopen if this PR is still being worked on.

@github-actions

Copy link
Copy Markdown
Contributor

This PR was marked stale due to lack of activity. It will be closed in 14 days.

@dpaasman00

Copy link
Copy Markdown
Contributor

Will be closing this PR and opening a new set of PRs to add this functionality in stages.

@evan-bradley

Copy link
Copy Markdown
Member

Closing in favor of #47300 and subsequent PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cmd/opampsupervisor Run Windows Enable running windows test on a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement package manager in supervisor