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

Implement add profile to install a profile to a cluster #1360

Merged
merged 15 commits into from
Feb 3, 2022

Conversation

nikimanoledaki
Copy link

@nikimanoledaki nikimanoledaki commented Jan 28, 2022

Closes: #1109

What changed? Why?
This PR adds the ability to install a profile to a cluster.

Usage

Minimum/required flags:
gitops add profile --name=podinfo --cluster=prod --config-repo=ssh://[email protected]/owner/config-repo.git

Optional flags:

  • --namespace defaults to wego-system
  • --version defaults to latest
  • --port for the Profiles API port
  • --auto-merge
  • --kubeconfig

Implementation Notes

  1. The HelmRepository Flux resource that contains the Chart must already be present and available for installation in the cluster.
  2. add profile discovers the HelmRepository's name and namespace through a Get query to the Profiles API. While this PR tries to rely on the Git provider API to use the .weave-gitops directory as the Source of Truth, add profile defers to get profiles to discover the HelmRepository's name and namespace, and its workflow still requires access to the cluster through a local kubeconfig. However, this will become optional as part of the following ticket: Add support for installing a profile without requiring kubeconfig access #1371
  3. add profile creates a HelmRelease that references the HelmRepository name and namespace.
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: nginx
  namespace: wego-system
spec:
  releaseName: nginx
  chart: 
    spec:
      chart: nginx
      sourceRef:
        kind: HelmRepository
        name: // discovered by Get Profiles
        namespace: wego-system // discovered by Get Profiles
      Version: 0.0.1
  interval: 1m
status: {}
  1. If no other HelmRelease exists with the same name/version/namespace/cluster combination in the config repository's Profiles manifest located at /.weave-gitops/clusters/<cluster name>/system/profiles.yaml, add profile appends the new HelmRelease to it. Otherwise, it returns an error.
.weave-gitops
└── clusters
    	└── prod
    		└── system
        		└── profiles.yaml // kind: HelmRelease
  1. Flux watches the profile.yaml file for new HelmReleases and installs them.

GitProvider interface additions

  • This PR implements gitprovider.GetRepoFiles to fetch a repo's subdirectory and its files. It's essentially a wrapper around go-git-providers to use .Files().Get(ctx, path, branch). add profile uses this func to get the /weave-gitops/clusters/<cluster-name>/system/profiles.yaml file from the config repo to read/append HelmReleases to it.

  • This PR also implements gitprovider.MergePullRequest to merge a PR through the Git provider API without relying on a local clone of the config repo. auto-merge in the acceptance tests uses this function.

How did you test it?

Manual Test

// Create cluster
kind create cluster --name test-01

// Edit `manifests/wego-app/deployment.yaml` to point to own container registry & build/push image
docker build -t niki2401/wego-app:latest -f Dockerfile . && docker push niki2401/wego-app:latest

// Make binary
make bin

// Install gitops
./bin/gitops install --config-repo ssh://[email protected]/nikimanoledaki/fun-times.git --auto-merge

// Create helmrepository 
touch helmrepo.yaml
cat <<EOF >./helmrepo.yaml 
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
  name: weaveworks-charts
  namespace: wego-system
spec:
  interval: 1m0s
  timeout: 1m0s
  url: https://weaveworks.github.io/profiles-examples
EOF
k apply -f helmrepo.yaml 

// Port-forward wego-app API
k port-forward pod/wego-app-<generated name> 9001 9001 -n wego-system

// Install Profile
./bin/gitops add profile --name podinfo --config-repo ssh://[email protected]/nikimanoledaki/fun-times.git --cluster kind-test-01 --version 6.0.0 --auto-merge
► getting available profiles in kind-test-01/wego-system
► Pull Request created: https://github.com/nikimanoledaki/fun-times/pull/29
► auto-merge=true; merging PR number 29
Adding profile:

Name: podinfo
Version: 6.0.0
Cluster: kind-test-01
Namespace: wego-system

// check profile is running
k get pods -A
wego-system          pod/kind-test-01-podinfo-569494d49d-xch8m           1/1     Running   0          30s

Acceptance Test

Release notes

Documentation Changes
Not sure where to add docs for this? 🤔

@nikimanoledaki nikimanoledaki changed the title [WIP] Implement add profile to install a profile to a cluster Implement add profile to install a profile to a cluster Jan 31, 2022
@nikimanoledaki nikimanoledaki marked this pull request as ready for review January 31, 2022 15:36
@nikimanoledaki nikimanoledaki requested a review from cPu1 January 31, 2022 15:48
func AddCommand(client *resty.Client) *cobra.Command {
cmd := &cobra.Command{
Use: "profile",
Aliases: []string{"profiles"},
Copy link
Contributor

Choose a reason for hiding this comment

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

do we want the alias since you can only install 1 at a time?

Copy link
Contributor

Choose a reason for hiding this comment

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

pkg/helm/releases.go Outdated Show resolved Hide resolved
cmd/gitops/add/cmd.go Outdated Show resolved Hide resolved
cmd/gitops/add/profiles/cmd.go Outdated Show resolved Hide resolved
cmd/gitops/add/profiles/cmd.go Outdated Show resolved Hide resolved
}
}

func validateAddOptions(opts profiles.AddOptions) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

This sets up an unfortunate error pattern, where you run it and it tells you something is invalid, so you fix it, and then you run it again, and it tells you something else is invalid.

Maybe a multierror would be better?

At least, return a slice of strings with all the errors.

Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't the problem that these depend on each other? If opts.Name is not defined, you can't call ApplicationNameTooLong. And then you can't call HasPrefix either. Though I agree that ConfigRepo and Cluster could be checked separately.

Copy link
Author

Choose a reason for hiding this comment

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

Changed this in the commit that addresses review feedback - the validateAddOptions func only has 2 checks in it now since I moved the required flags to Cobra's feature for checking for required flags.

cmd/gitops/add/profiles/cmd_test.go Outdated Show resolved Hide resolved
pkg/helm/releases.go Outdated Show resolved Hide resolved
pkg/models/manifest.go Outdated Show resolved Hide resolved
nikimanoledaki added 4 commits February 2, 2022 17:35
- MergePullRequest uses go-git-provider to merge a pull request from a repository, given that repo's URL and the PR number.
- Improve acceptance test for Profiles service
- Improve logic for creating kind clusters to avoid duplicate prefix e.g. kind-kind-x
- removed all `Expect(err).NotTo(BeNil)` before `MatchError()` assertions
- refactored how we discover version of available profiles to return it rather than set it on pb profile
- pass in all values for MakeHelmRelease to remove Profiles dependency
- renamed --port to --profiles-port
- use a single const for profiles path (git.ProfilesManifestFileName) instead of models.WegoProfilePath
- seed with time at the start of the cmd for late use of rand
- improve function name and documentation comment for splitYAML() and GetRandomString()
- use Cobra's MarkFlagRequired feature for name, cluster, and config-repo flags
- change gitproviders.MergePullRequest() to always use method Merge
- uses ConvertStringListToSemanticVersionList() and SortVersions() to sort semver versions of Profile's available versions
- checkout package-lock.json to reset it to that of main
- removed *resty.Client from addRunE command
- moved profiles.yaml const to pkg models
- added --kubeconfig flag
- renamed GetRepoFiles() to GetRepoDirFiles()
- renamed MakeManifestFile() to AppendProfileToFile()
- renamed GetAvailableProfile() to GetProfile()
- MakeHelmRelease compares HelmReleases with go-cmp (very cool)

Co-authored-by: Jake Klein <[email protected]>
Co-authored-by: Gergely Brautigam <[email protected]>
Co-authored-by: Chetan Patwal <[email protected]>
@nikimanoledaki
Copy link
Author

Hey folks 👋 @aclevername @Skarlso @cPu1 @Himangini @bigkevmcd @jpellizzari

Thank you all for the reviews! I've responded to and/or addressed all feedback. I didn't want to spam everyone by responding with Done! 50 times so I marked each comment that was addressed and completed with a "👍". The commit that addresses all review feedback (not linking it since it'll change anyway) also contains a list of all the requested changes for this round of reviews. :)

Feel free to mark any leftover comment as resolved and/or review and comment more!

PS: integration tests + linter currently pass ✅

Copy link
Contributor

@Himangini Himangini left a comment

Choose a reason for hiding this comment

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

Well done Niki 👏🏻 , I have gone through all the files and have a few minor comments, otherwise the PR looks pretty good to me 🎉

pkg/services/profiles/add.go Outdated Show resolved Hide resolved
pkg/services/profiles/add.go Show resolved Hide resolved
pkg/services/automation/generator.go Outdated Show resolved Hide resolved
tools/testcrds/helm.toolkit.fluxcd.io_helmreleases.yaml Outdated Show resolved Hide resolved
@Himangini
Copy link
Contributor

For Documentation, adding something under https://docs.gitops.weave.works/docs/cluster-management/profiles section should be sufficient I think. cc @sympatheticmoose @josefaworks wdyt?

Copy link
Contributor

@Skarlso Skarlso left a comment

Choose a reason for hiding this comment

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

LGTM with that one last break addition. :) And Kevin's comment about the possible too long name.

@nikimanoledaki nikimanoledaki force-pushed the add-profile branch 2 times, most recently from 4f77b16 to b40f6f7 Compare February 3, 2022 10:15
Copy link
Contributor

@Himangini Himangini left a comment

Choose a reason for hiding this comment

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

🎉 👍🏻

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

Successfully merging this pull request may close these issues.

Add gitops add/apply profile/profiles command
7 participants