Skip to content
This repository has been archived by the owner on Jul 15, 2024. It is now read-only.

Add support for generating based on scraping the Github API. #209

Merged
merged 23 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7786079
✨ Add support for generating based on scraping the Github API.
coderanger Apr 23, 2021
3396bf6
🎨 Switch to the non-deprecated way to make a fake client.
coderanger Apr 23, 2021
bb49ab9
🎨 Go mod tidy.
coderanger Apr 23, 2021
161a81b
🎨 Sync the install manifests too.
coderanger Apr 23, 2021
0377be1
🎨 Refactor to a table test.
coderanger Apr 23, 2021
41dcea8
📝 Docs for the repo host generator.
coderanger Apr 23, 2021
d7b4f18
📝 Example for repo host generator.
coderanger Apr 23, 2021
f5d0939
🎨 Add an E2E test for repo host generator.
coderanger Apr 23, 2021
450c2a1
✏️ Typo in my E2E test.
coderanger Apr 24, 2021
25ef713
🎨 Regenerate the manifests with controller-get 0.3.0.
coderanger Apr 24, 2021
949f525
Merge branch 'master' into github-generator
coderanger Apr 25, 2021
4182e1f
🎨 Regenerate the manifests with fixed Kustomize version.
coderanger Apr 25, 2021
11b4d44
🎨 Tweaks from code review.
coderanger Apr 30, 2021
370aff8
✨ Add three new features, branchMatch filters, allBranches scanning m…
coderanger May 3, 2021
8635530
🎨 Add a test for addBranches mode.
coderanger May 3, 2021
3ca3903
📝 Remove outdated line re: which branches are scanned.
coderanger May 3, 2021
a61120e
🎨 Name -> SecretName for clarity since it doesn't otherwise say it's …
coderanger May 3, 2021
a9fe5f4
🎨 Mass rename of the subsystem from "repo host" to "SCM provider".
coderanger May 7, 2021
1b538e2
✨ Reflow the logic dealing with multiple filters so it's a clearer OR…
coderanger May 7, 2021
a50feb8
Merge branch 'master' into github-generator
coderanger May 7, 2021
b84e6b6
🎨 Post merge go.sum fixing.
coderanger May 7, 2021
1a9b058
🎨 Try to better handle rate limit errors from the GitHub unit tests.
coderanger May 7, 2021
ee81c7a
🎨 Switch the example to use https cloning since it's a public repo an…
coderanger May 10, 2021
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
54 changes: 51 additions & 3 deletions api/v1alpha1/applicationset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Utility struct for a reference to a secret key.
type SecretRef struct {
SecretName string `json:"secretName"`
Key string `json:"key"`
}

// ApplicationSet is a set of Application resources
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=applicationsets,shortName=appset;appsets
Expand Down Expand Up @@ -65,9 +71,10 @@ type ApplicationSetTemplateMeta struct {

// ApplicationSetGenerator include list item info
type ApplicationSetGenerator struct {
List *ListGenerator `json:"list,omitempty"`
Clusters *ClusterGenerator `json:"clusters,omitempty"`
Git *GitGenerator `json:"git,omitempty"`
List *ListGenerator `json:"list,omitempty"`
Clusters *ClusterGenerator `json:"clusters,omitempty"`
Git *GitGenerator `json:"git,omitempty"`
SCMProvider *SCMProviderGenerator `json:"scmProvider,omitempty"`
}

// ListGenerator include items info
Expand Down Expand Up @@ -114,6 +121,47 @@ type GitFileGeneratorItem struct {
Path string `json:"path"`
}

// SCMProviderGenerator defines a generator that scrapes a SCMaaS API to find candidate repos.
type SCMProviderGenerator struct {
// Which provider to use and config for it.
Github *SCMProviderGeneratorGithub `json:"github,omitempty"`
// TODO other providers.
// Filters for which repos should be considered.
Filters []SCMProviderGeneratorFilter `json:"filters,omitempty"`
// Which protocol to use for the SCM URL. Default is provider-specific but ssh if possible. Not all providers
// necessarily support all protocols.
CloneProtocol string `json:"cloneProtocol,omitempty"`
// Standard parameters.
RequeueAfterSeconds *int64 `json:"requeueAfterSeconds,omitempty"`
Template ApplicationSetTemplate `json:"template,omitempty"`
}

// SCMProviderGeneratorGithub defines a connection info specific to GitHub.
type SCMProviderGeneratorGithub struct {
// GitHub org to scan. Required.
Organization string `json:"organization"`
// The GitHub API URL to talk to. If blank, use https://api.github.com/.
API string `json:"api,omitempty"`
// Authentication token reference.
TokenRef *SecretRef `json:"tokenRef,omitempty"`
// Scan all branches instead of just the default branch.
AllBranches bool `json:"allBranches,omitempty"`
}

// SCMProviderGeneratorFilter is a single repository filter.
// If multiple filter types are set on a single struct, they will be AND'd together. All filters must
// pass for a repo to be included.
type SCMProviderGeneratorFilter struct {
// A regex for repo names.
RepositoryMatch *string `json:"repositoryMatch,omitempty"`
// An array of paths, all of which must exist.
PathsExist []string `json:"pathsExist,omitempty"`
// A regex which must match at least one label.
LabelMatch *string `json:"labelMatch,omitempty"`
// A regex which must match the branch name.
BranchMatch *string `json:"branchMatch,omitempty"`
}

// ApplicationSetStatus defines the observed state of ApplicationSet
type ApplicationSetStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
Expand Down
108 changes: 108 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

121 changes: 121 additions & 0 deletions docs/Generators.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,124 @@ spec:
Any `config.json` files found under the `cluster-config` directory will be parameterized based on the `path` wildcard pattern specified. Within each file JSON fields are flattened into key/value pairs, with this ApplicationSet example using the `cluster.address` as `cluster.name` parameters in the template.

As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them.

## SCM Provider Generator

The SCMProvider generator uses the API of an SCMaaS provider to discover repositories. This fits well with many repos following the same GitOps layout patterns such as microservices.

Support is currently limited to GitHub, PRs are welcome to add more SCM providers.

```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapps
spec:
generators:
- scmProvider:
# Which protocol to clone using.
cloneProtocol: ssh
# See below for provider specific options.
github:
# ...
```

* `cloneProtocol`: Which protocol to use for the SCM URL. Default is provider-specific but ssh if possible. Not all providers necessarily support all protocols, see provider documentation below for available options.

### GitHub

The GitHub mode uses the GitHub API to scan and organization in either github.com or GitHub Enterprise.

```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapps
spec:
generators:
- scmProvider:
github:
# The GitHub organization to scan.
organization: myorg
# For GitHub Enterprise:
api: https://git.example.com/
# If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
allBranches: true
# Reference to a Secret containing an access token. (optional)
tokenRef:
secretName: github-token
key: token
template:
# ...
```

* `organization`: Required name of the GitHub organization to scan. If you have multiple orgs, use multiple generators.
* `api`: If using GitHub Enterprise, the URL to access it.
* `allBranches`: By default (false) the template will only be evaluated for the default branch of each repo. If this is true, every branch of every repository will be passed to the filters. If using this flag, you likely want to use a `branchMatch` filter.
* `tokenRef`: A Secret name and key containing the GitHub access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories.

For label filtering, the repository topics are used.

Available clone protocols are `ssh` and `https`.

### Filters

Filters allow selecting which repositories to generate for. Each filter can declare one or more conditions, all of which must pass. If multiple filters are present, any can match for a repository to be included. If no filters are specified, all repositories will be processed.

jgwest marked this conversation as resolved.
Show resolved Hide resolved
```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapps
spec:
generators:
- scmProvider:
filters:
# Include any repository starting with "myapp" AND including a Kustomize config AND labeled with "deploy-ok" ...
- repositoryMatch: ^myapp
pathsExist: [kubernetes/kustomization.yaml]
labelMatch: deploy-ok
# ... OR any repository starting with "otherapp" AND a Helm folder.
- repositoryMatch: ^otherapp
pathsExist: [helm]
template:
# ...
```

* `repositoryMatch`: A regexp matched against the repository name.
* `pathsExist`: An array of paths within the repository that must exist. Can be a file or directory, but do not include the trailing `/` for directories.
* `labelMatch`: A regexp matched against repository labels. If any label matches, the repository is included.
* `branchMatch`: A regexp matched against branch names.

jgwest marked this conversation as resolved.
Show resolved Hide resolved
### Template

As with all generators, several keys are available for replacement in the generated application.

```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: myapps
spec:
generators:
- scmProvider:
# ...
template:
metadata:
name: '{{ repository }}'
spec:
source:
repoURL: '{{ url }}'
targetRevision: '{{ branch }}'
path: kubernetes/
project: default
destination:
server: https://kubernetes.default.svc
namespace: default
```

* `organization`: The name of the organization the repository is in.
* `repository`: The name of the repository.
* `url`: The clone URL for the repository.
* `branch`: The default branch of the repository.
coderanger marked this conversation as resolved.
Show resolved Hide resolved

24 changes: 24 additions & 0 deletions examples/scm-provider-generator/scm-provider-example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: guestbook
spec:
generators:
- scmProvider:
jgwest marked this conversation as resolved.
Show resolved Hide resolved
github:
organization: argoproj
cloneProtocol: https
filters:
- repositoryMatch: example-apps
template:
metadata:
name: '{{ repository }}-guestbook'
spec:
project: "default"
source:
repoURL: '{{ url }}'
targetRevision: '{{ branch }}'
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ require (
github.com/argoproj/gitops-engine v0.2.1
github.com/argoproj/pkg v0.2.0
github.com/go-logr/logr v0.3.0
github.com/google/go-github/v35 v35.0.0
github.com/imdario/mergo v0.3.10
github.com/jeremywohl/flatten v1.0.1
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.6.0
github.com/stretchr/testify v1.6.1
github.com/valyala/fasttemplate v1.2.1
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78
k8s.io/api v0.19.2
k8s.io/apimachinery v0.19.2
k8s.io/client-go v11.0.1-0.20190816222228-6d55c1b1f1ca+incompatible
Expand Down
Loading