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

Added support for legacy Helm chart repositories #58

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

frizzr
Copy link

@frizzr frizzr commented Jan 14, 2025

This change adds support for legacy (non-OCI) Helm chart repositories in the least-disruptive way to the existing API.

I will add unit tests if the maintainers are initially okay with this. If not, I could instead refactor the code to add a separate method with a different name and the different signature.

If not interested in adding legacy Helm repo support at all, just say so and I'll close my PR.

Thanks for your consideration!

Russ

@frizzr frizzr marked this pull request as ready for review January 14, 2025 17:14
@RetGal
Copy link
Contributor

RetGal commented Jan 15, 2025

The PR looks fine, as it extends functionality and maintains API compatibility.
Of course it would be extra nice if you could also extend the test and examples.
But in any case, thank you very much for your contribution, which is greatly appreciated!

@RetGal
Copy link
Contributor

RetGal commented Jan 16, 2025

@frizzr Could you perhaps give us an example usage of helm push to a non oci registry?

@frizzr
Copy link
Author

frizzr commented Jan 20, 2025

@frizzr Could you perhaps give us an example usage of helm push to a non oci registry?

Yes. I'll get something together in the next day or two.

@frizzr
Copy link
Author

frizzr commented Jan 20, 2025

I'll need to create additional code to send a Helm chart package to a legacy Helm repository. There is no built-in helm command to upload a chart to a non-OCI repository. Helm only added the push command for OCI.

A legacy Helm repository is just a file server that handles HTTP(S) file uploads. In a CI/CD process we normally use curl and use basic authentication, so given your base image has curl on it, I can go ahead and use that if you have no objections.

The way I will write it is that the user will need to prefix any vendor-specific pathing as part of the repository string. For example, JFrog Artifactory usually requires artifactory after the registry (hostname) and then the repository name and the folder path.

So, for those who want to send a chart to Artifactory hosted at artifactory.mycompany.com and the name of the Helm chart repository is myteam-helm, then the user would need to issue the following:

dagger call package-push \
  --registry artifactory.mycompany.com \
  --repository artifactory/myteam-helm \
  --username $REGISTRY_HELM_USER \
  --password env:REGISTRY_HELM_PASSWORD \
  --directory ./examples/testdata/mychart/ \
  --use-non-oci-helm-repo=true

Another difference with non-OCI repositories is that you can put the packaged chart in any subpath in the destination repository, so similarly, we would allow the user to suffix that pathing to the repository parameter.

Continuing the example, if the user wanted to put the chart in a products/my-team-product subpath in the repository, then the command issued would be

dagger call package-push \
  --registry artifactory.mycompany.com \
  --repository artifactory/myteam-helm/products/my-team-product \
  --username $REGISTRY_HELM_USER \
...

Finally, I'm open to even adding a new Dagger function to your API if you feel this is overloading things too much with the existing API, or creating additional optional parameters with the existing function. In short, I'm flexible and willing to abide by any API guidance you provide.

Still, maybe all of this is a deal-breaker for you if you only want to include commands that Helm directly supports or assume that the proposed support will only be for HTTPS Basic Authentication.

I'll have to write the code either way (since I am making a wrapper around your module anyway given our in-company API is different) but I fully understand whatever you decide.

@RetGal
Copy link
Contributor

RetGal commented Jan 21, 2025

OK, thank you for the clarifications!

I think it's fine to use curl rather than adding another binary to the image.

Basicly the existing helm push command
[]string{"helm", "push", fmt.Sprintf("%s-%s.tgz", name, version), opts.getRepoFqdn()}
would be replaced by something like this for non oci then:
[]string{"curl", "-X", "PUT", "-u", fmt.Sprintf("%s:%s", opts.Username, opts.Password), "--data-binary", fmt.Sprintf("%s-%s.tgz", name, version), opts.getChartFqdn()}

This logic could be put in a separate function, which then could be called inside the WithExec statement:

func (p PushOpts) getPushCommand(name string, version string) []string {
	if p.Oci {
		return []string{"helm", "push", fmt.Sprintf("%s-%s.tgz", name, version), p.getRepoFqdn()}
	}
	return []string{"curl", "-X", "PUT", "-u", fmt.Sprintf("%s:%s", p.Username, p.Password), "--data-binary", fmt.Sprintf("%s-%s.tgz", name, version), p.getChartFqdn(name)}
}

WithExec(opts.getPushCommand(name, version)).

@frizzr
Copy link
Author

frizzr commented Jan 21, 2025

The only concern I have with your suggestion of putting the push command function in PushOpts would be that the password secret would be exposed since we are grabbing it from the struct and not running it through WithSecretVariable. Maybe I am misunderstanding how secret variables work with Dagger. I'm still new to it all.

For now I will just inline the logic in PackagePush. Feel free to suggest other approaches or to educate me. Thanks!

@RetGal
Copy link
Contributor

RetGal commented Jan 21, 2025

That's actually a good point! I'll leave the further implementation up to you =)

@frizzr
Copy link
Author

frizzr commented Jan 21, 2025

Okay. Initial code added. I'll now test it.

@frizzr
Copy link
Author

frizzr commented Jan 25, 2025

I was able to test that non-OCI charts do upload successfully and the logic for detecting if the chart already exists on the server is also working for non-OCI charts.

Would it be possible for you to test OCI charts with this code?

I did have to change the new boolean flag from --oci to --use-non-oci-helm-repo and reverse its polarity due to this current issue with default=true when using a module from Go:

dagger/dagger#8810

@RetGal
Copy link
Contributor

RetGal commented Jan 28, 2025

Thank you, looks great! Just one last thing: I added a test for the existing chart check.
Could you please rebase and check if the new functionality also passes the test?

Copy link
Member

@chrira chrira left a comment

Choose a reason for hiding this comment

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

Thank you @frizzr for your contributions!
We added tests for the PackagePush return logic.
Please rebase your PR onto main.
Then you'll see, that a test fails.
I commented the problems of your solution.

@@ -58,7 +60,7 @@ func (h *Helm) Version(
return strings.TrimSpace(version), nil
}

// Packages and pushes a Helm chart to a specified OCI-compatible registry with authentication.
// Packages and pushes a Helm chart to a specified OCI-compatible (by default) registry with authentication.
//
// Returns true if the chart was successfully pushed, or false if the chart already exists, with error handling for push failures.
Copy link
Member

Choose a reason for hiding this comment

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

This is the behavior of the method for existing or not existing versions. Errors are only thrown for technical reasons.

Copy link
Author

Choose a reason for hiding this comment

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

I believe the commit I made resolves this. Let me know for sure. Thanks!

helm/main.go Outdated Show resolved Hide resolved
@frizzr frizzr requested a review from chrira January 30, 2025 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants