Merge pull request #31 from fluxcd/bootstrap-github

Implement GitHub repository bootstrap
pull/35/head
Stefan Prodan 5 years ago committed by GitHub
commit dc7c2ce56b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,20 @@
package main
import (
"github.com/spf13/cobra"
)
var bootstrapCmd = &cobra.Command{
Use: "bootstrap",
Short: "Bootstrap commands",
}
var (
bootstrapVersion string
)
func init() {
bootstrapCmd.PersistentFlags().StringVar(&bootstrapVersion, "version", "master", "toolkit tag or branch")
rootCmd.AddCommand(bootstrapCmd)
}

@ -0,0 +1,534 @@
package main
import (
"context"
"fmt"
"io/ioutil"
"net/url"
"os"
"path"
"path/filepath"
"sigs.k8s.io/yaml"
"strings"
"time"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/google/go-github/v32/github"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1alpha1"
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
)
var bootstrapGitHubCmd = &cobra.Command{
Use: "github",
Short: "Bootstrap GitHub repository",
Long: `
The bootstrap command creates the GitHub repository if it doesn't exists and
commits the toolkit components manifests to the master branch.
Then it configure the target cluster to synchronize with the repository.
If the toolkit components are present on the cluster,
the bootstrap command will perform an upgrade if needed.`,
Example: ` # Create a GitHub personal access token and export it as an env var
export GITHUB_TOKEN=<my-token>
# Run bootstrap for a private repo owned by a GitHub organization
bootstrap github --owner=<organization> --repository=<repo name>
# Run bootstrap for a public repository on a personal account
bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true
# Run bootstrap for a private repo hosted on GitHub Enterprise
bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain>
`,
RunE: bootstrapGitHubCmdRun,
}
var (
ghOwner string
ghRepository string
ghInterval time.Duration
ghPersonal bool
ghPrivate bool
ghHostname string
)
const (
ghTokenName = "GITHUB_TOKEN"
ghBranch = "master"
ghInstallManifest = "toolkit.yaml"
ghSourceManifest = "toolkit-source.yaml"
ghKustomizationManifest = "toolkit-kustomization.yaml"
ghDefaultHostname = "github.com"
)
func init() {
bootstrapGitHubCmd.Flags().StringVar(&ghOwner, "owner", "", "GitHub user or organization name")
bootstrapGitHubCmd.Flags().StringVar(&ghRepository, "repository", "", "GitHub repository name")
bootstrapGitHubCmd.Flags().BoolVar(&ghPersonal, "personal", false, "is personal repository")
bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "is private repository")
bootstrapGitHubCmd.Flags().DurationVar(&ghInterval, "interval", time.Minute, "sync interval")
bootstrapGitHubCmd.Flags().StringVar(&ghHostname, "hostname", ghDefaultHostname, "GitHub hostname")
bootstrapCmd.AddCommand(bootstrapGitHubCmd)
}
func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
ghToken := os.Getenv(ghTokenName)
if ghToken == "" {
return fmt.Errorf("%s environment variable not found", ghTokenName)
}
ghURL := fmt.Sprintf("https://%s/%s/%s", ghHostname, ghOwner, ghRepository)
sshURL := fmt.Sprintf("ssh://git@%s/%s/%s", ghHostname, ghOwner, ghRepository)
if ghOwner == "" || ghRepository == "" {
return fmt.Errorf("owner and repository are required")
}
kubeClient, err := utils.kubeClient(kubeconfig)
if err != nil {
return err
}
tmpDir, err := ioutil.TempDir("", namespace)
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// create GitHub repository if doesn't exists
logAction("connecting to %s", ghHostname)
if err := createGitHubRepository(ctx, ghHostname, ghOwner, ghRepository, ghToken, ghPrivate, ghPersonal); err != nil {
return err
}
// clone repository and checkout the master branch
repo, err := checkoutGitHubRepository(ctx, ghURL, ghBranch, ghToken, tmpDir)
if err != nil {
return err
}
logSuccess("repository cloned")
// generate install manifests
logGenerate("generating manifests")
manifest, err := generateGitHubInstall(namespace, tmpDir)
if err != nil {
return err
}
// stage install manifests
changed, err := commitGitHubManifests(repo, namespace)
if err != nil {
return err
}
// push install manifests
if changed {
if err := pushGitHubRepository(ctx, repo, ghToken); err != nil {
return err
}
logSuccess("components manifests pushed")
} else {
logSuccess("components are up to date")
}
// determine if repo synchronization is working
isInstall := shouldInstallGitHub(ctx, kubeClient, namespace)
if isInstall {
// apply install manifests
logAction("installing components in %s namespace", namespace)
command := fmt.Sprintf("kubectl apply -f %s", manifest)
if _, err := utils.execCommand(ctx, ModeOS, command); err != nil {
return fmt.Errorf("install failed")
}
logSuccess("install completed")
// check installation
logWaiting("verifying installation")
for _, deployment := range components {
command = fmt.Sprintf("kubectl -n %s rollout status deployment %s --timeout=%s",
namespace, deployment, timeout.String())
if _, err := utils.execCommand(ctx, ModeOS, command); err != nil {
return fmt.Errorf("install failed")
} else {
logSuccess("%s ready", deployment)
}
}
}
// setup SSH deploy key
if shouldCreateGitHubDeployKey(ctx, kubeClient, namespace) {
logAction("configuring deploy key")
u, err := url.Parse(sshURL)
if err != nil {
return fmt.Errorf("git URL parse failed: %w", err)
}
key, err := generateGitHubDeployKey(ctx, kubeClient, u, namespace)
if err != nil {
return fmt.Errorf("generating deploy key failed: %w", err)
}
if err := createGitHubDeployKey(ctx, key, ghHostname, ghOwner, ghRepository, ghToken, ghPersonal); err != nil {
return err
}
logSuccess("deploy key configured")
}
// configure repo synchronization
if isInstall {
// generate source and kustomization manifests
logAction("generating sync manifests")
if err := generateGitHubKustomization(sshURL, namespace, namespace, tmpDir, ghInterval); err != nil {
return err
}
// stage manifests
changed, err = commitGitHubManifests(repo, namespace)
if err != nil {
return err
}
// push manifests
if changed {
if err := pushGitHubRepository(ctx, repo, ghToken); err != nil {
return err
}
}
logSuccess("sync manifests pushed")
// apply manifests and waiting for sync
logAction("applying sync manifests")
if err := applyGitHubKustomization(ctx, kubeClient, namespace, namespace, tmpDir); err != nil {
return err
}
}
logSuccess("bootstrap finished")
return nil
}
func makeGitHubClient(hostname, token string) (*github.Client, error) {
auth := github.BasicAuthTransport{
Username: "git",
Password: token,
}
gh := github.NewClient(auth.Client())
if hostname != ghDefaultHostname {
baseURL := fmt.Sprintf("https://%s/api/v3/", hostname)
uploadURL := fmt.Sprintf("https://%s/api/uploads/", hostname)
if g, err := github.NewEnterpriseClient(baseURL, uploadURL, auth.Client()); err == nil {
gh = g
} else {
return nil, fmt.Errorf("github client error: %w", err)
}
}
return gh, nil
}
func createGitHubRepository(ctx context.Context, hostname, owner, name, token string, isPrivate, isPersonal bool) error {
gh, err := makeGitHubClient(hostname, token)
if err != nil {
return err
}
org := ""
if !isPersonal {
org = owner
}
if _, _, err := gh.Repositories.Get(ctx, org, name); err == nil {
return nil
}
autoInit := true
_, _, err = gh.Repositories.Create(ctx, org, &github.Repository{
AutoInit: &autoInit,
Name: &name,
Private: &isPrivate,
})
if err != nil {
if !strings.Contains(err.Error(), "name already exists on this account") {
return fmt.Errorf("github create repository error: %w", err)
}
} else {
logSuccess("repository created")
}
return nil
}
func checkoutGitHubRepository(ctx context.Context, url, branch, token, path string) (*git.Repository, error) {
auth := &http.BasicAuth{
Username: "git",
Password: token,
}
repo, err := git.PlainCloneContext(ctx, path, false, &git.CloneOptions{
URL: url,
Auth: auth,
RemoteName: git.DefaultRemoteName,
ReferenceName: plumbing.NewBranchReferenceName(branch),
SingleBranch: true,
NoCheckout: false,
Progress: nil,
Tags: git.NoTags,
})
if err != nil {
return nil, fmt.Errorf("git clone error: %w", err)
}
_, err = repo.Head()
if err != nil {
return nil, fmt.Errorf("git resolve HEAD error: %w", err)
}
return repo, nil
}
func generateGitHubInstall(namespace, tmpDir string) (string, error) {
tkDir := path.Join(tmpDir, ".tk")
defer os.RemoveAll(tkDir)
if err := os.MkdirAll(tkDir, os.ModePerm); err != nil {
return "", fmt.Errorf("generating manifests failed: %w", err)
}
if err := genInstallManifests(bootstrapVersion, namespace, components, tkDir); err != nil {
return "", fmt.Errorf("generating manifests failed: %w", err)
}
manifestsDir := path.Join(tmpDir, namespace)
if err := os.MkdirAll(manifestsDir, os.ModePerm); err != nil {
return "", fmt.Errorf("generating manifests failed: %w", err)
}
manifest := path.Join(manifestsDir, ghInstallManifest)
if err := buildKustomization(tkDir, manifest); err != nil {
return "", fmt.Errorf("build kustomization failed: %w", err)
}
return manifest, nil
}
func commitGitHubManifests(repo *git.Repository, namespace string) (bool, error) {
w, err := repo.Worktree()
if err != nil {
return false, err
}
_, err = w.Add(namespace)
if err != nil {
return false, err
}
status, err := w.Status()
if err != nil {
return false, err
}
if !status.IsClean() {
if _, err := w.Commit("Add manifests", &git.CommitOptions{
Author: &object.Signature{
Name: "tk",
Email: "tk@users.noreply.github.com",
When: time.Now(),
},
}); err != nil {
return false, err
}
return true, nil
}
return false, nil
}
func pushGitHubRepository(ctx context.Context, repo *git.Repository, token string) error {
auth := &http.BasicAuth{
Username: "git",
Password: token,
}
err := repo.PushContext(ctx, &git.PushOptions{
Auth: auth,
Progress: nil,
})
if err != nil {
return fmt.Errorf("git push error: %w", err)
}
return nil
}
func generateGitHubKustomization(url, name, namespace, tmpDir string, interval time.Duration) error {
gvk := sourcev1.GroupVersion.WithKind("GitRepository")
gitRepository := sourcev1.GitRepository{
TypeMeta: metav1.TypeMeta{
Kind: gvk.Kind,
APIVersion: gvk.GroupVersion().String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: sourcev1.GitRepositorySpec{
URL: url,
Interval: metav1.Duration{
Duration: interval,
},
Reference: &sourcev1.GitRepositoryRef{
Branch: "master",
},
SecretRef: &corev1.LocalObjectReference{
Name: name,
},
},
}
gitData, err := yaml.Marshal(gitRepository)
if err != nil {
return err
}
if err := utils.writeFile(string(gitData), filepath.Join(tmpDir, namespace, ghSourceManifest)); err != nil {
return err
}
gvk = kustomizev1.GroupVersion.WithKind("Kustomization")
emptyAPIGroup := ""
kustomization := kustomizev1.Kustomization{
TypeMeta: metav1.TypeMeta{
Kind: gvk.Kind,
APIVersion: gvk.GroupVersion().String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: kustomizev1.KustomizationSpec{
Interval: metav1.Duration{
Duration: 10 * time.Minute,
},
Path: "./",
Prune: true,
SourceRef: corev1.TypedLocalObjectReference{
APIGroup: &emptyAPIGroup,
Kind: "GitRepository",
Name: name,
},
},
}
ksData, err := yaml.Marshal(kustomization)
if err != nil {
return err
}
if err := utils.writeFile(string(ksData), filepath.Join(tmpDir, namespace, ghKustomizationManifest)); err != nil {
return err
}
return nil
}
func applyGitHubKustomization(ctx context.Context, kubeClient client.Client, name, namespace, tmpDir string) error {
command := fmt.Sprintf("kubectl apply -f %s", filepath.Join(tmpDir, namespace))
if _, err := utils.execCommand(ctx, ModeStderrOS, command); err != nil {
return err
}
logWaiting("waiting for cluster sync")
if err := wait.PollImmediate(pollInterval, timeout,
isGitRepositoryReady(ctx, kubeClient, name, namespace)); err != nil {
return err
}
if err := wait.PollImmediate(pollInterval, timeout,
isKustomizationReady(ctx, kubeClient, name, namespace)); err != nil {
return err
}
return nil
}
func shouldInstallGitHub(ctx context.Context, kubeClient client.Client, namespace string) bool {
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: namespace,
}
var kustomization kustomizev1.Kustomization
if err := kubeClient.Get(ctx, namespacedName, &kustomization); err != nil {
return true
}
return kustomization.Status.LastAppliedRevision == ""
}
func shouldCreateGitHubDeployKey(ctx context.Context, kubeClient client.Client, namespace string) bool {
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: namespace,
}
var existing corev1.Secret
if err := kubeClient.Get(ctx, namespacedName, &existing); err != nil {
return true
}
return false
}
func generateGitHubDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) {
pair, err := generateKeyPair(ctx)
if err != nil {
return "", err
}
hostKey, err := scanHostKey(ctx, url)
if err != nil {
return "", err
}
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Namespace: namespace,
},
StringData: map[string]string{
"identity": string(pair.PrivateKey),
"identity.pub": string(pair.PublicKey),
"known_hosts": string(hostKey),
},
}
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return "", err
}
return string(pair.PublicKey), nil
}
func createGitHubDeployKey(ctx context.Context, key, hostname, owner, name, token string, isPersonal bool) error {
gh, err := makeGitHubClient(hostname, token)
if err != nil {
return err
}
keyName := fmt.Sprintf("tk-%s", namespace)
isReadOnly := true
_, _, err = gh.Repositories.CreateKey(ctx, owner, name, &github.Key{
Title: &keyName,
Key: &key,
ReadOnly: &isReadOnly,
})
if err != nil {
return fmt.Errorf("github create deploy key error: %w", err)
}
return nil
}

@ -13,9 +13,11 @@ var createCmd = &cobra.Command{
var (
interval time.Duration
export bool
)
func init() {
createCmd.PersistentFlags().DurationVarP(&interval, "interval", "", time.Minute, "source sync interval")
createCmd.PersistentFlags().BoolVar(&export, "export", false, "export in yaml format to stdout")
rootCmd.AddCommand(createCmd)
}

@ -3,11 +3,9 @@ package main
import (
"context"
"fmt"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1alpha1"
"strings"
"time"
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
@ -15,6 +13,9 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1alpha1"
sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1"
)
var createKsCmd = &cobra.Command{
@ -106,7 +107,9 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
return err
}
logGenerate("generating kustomization")
if !export {
logGenerate("generating kustomization")
}
emptyAPIGroup := ""
kustomization := kustomizev1.Kustomization{
@ -171,6 +174,10 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
}
}
if export {
return exportKs(kustomization)
}
logAction("applying kustomization")
if err := upsertKustomization(ctx, kubeClient, kustomization); err != nil {
return err

@ -121,6 +121,32 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err
}
gitRepository := sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: sourcev1.GitRepositorySpec{
URL: sourceGitURL,
Interval: metav1.Duration{
Duration: interval,
},
Reference: &sourcev1.GitRepositoryRef{},
},
}
if sourceGitSemver != "" {
gitRepository.Spec.Reference.SemVer = sourceGitSemver
} else if sourceGitTag != "" {
gitRepository.Spec.Reference.Tag = sourceGitTag
} else {
gitRepository.Spec.Reference.Branch = sourceGitBranch
}
if export {
return exportGit(gitRepository)
}
withAuth := false
// TODO(hidde): move all auth prep to separate func?
if u.Scheme == "ssh" {
@ -187,34 +213,12 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
logGenerate("generating source")
gitRepository := sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: sourcev1.GitRepositorySpec{
URL: sourceGitURL,
Interval: metav1.Duration{
Duration: interval,
},
Reference: &sourcev1.GitRepositoryRef{},
},
}
if withAuth {
gitRepository.Spec.SecretRef = &corev1.LocalObjectReference{
Name: name,
}
}
if sourceGitSemver != "" {
gitRepository.Spec.Reference.SemVer = sourceGitSemver
} else if sourceGitTag != "" {
gitRepository.Spec.Reference.Tag = sourceGitTag
} else {
gitRepository.Spec.Reference.Branch = sourceGitBranch
}
logAction("applying source")
if err := upsertGitRepository(ctx, kubeClient, gitRepository); err != nil {
return err
@ -287,7 +291,7 @@ func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.S
err := kubeClient.Get(ctx, namespacedName, &existing)
if err != nil {
if errors.IsNotFound(err) {
if err := kubeClient.Create(ctx, &existing); err != nil {
if err := kubeClient.Create(ctx, &secret); err != nil {
return err
} else {
return nil

@ -112,3 +112,18 @@ func (*Utils) kubeClient(config string) (client.Client, error) {
return kubeClient, nil
}
func (*Utils) writeFile(content, filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = io.WriteString(file, content)
if err != nil {
return err
}
return file.Sync()
}

@ -77,6 +77,7 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.
### SEE ALSO
* [tk bootstrap](tk_bootstrap.md) - Bootstrap commands
* [tk check](tk_check.md) - Check requirements and installation
* [tk completion](tk_completion.md) - Generates bash completion scripts
* [tk create](tk_create.md) - Create commands
@ -89,4 +90,4 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.
* [tk sync](tk_sync.md) - Synchronize commands
* [tk uninstall](tk_uninstall.md) - Uninstall the toolkit components
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -0,0 +1,31 @@
## tk bootstrap
Bootstrap commands
### Synopsis
Bootstrap commands
### Options
```
-h, --help help for bootstrap
--version string toolkit tag or branch (default "master")
```
### Options inherited from parent commands
```
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller])
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--namespace string the namespace scope for this operation (default "gitops-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
* [tk bootstrap github](tk_bootstrap_github.md) - Bootstrap GitHub repository
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -0,0 +1,62 @@
## tk bootstrap github
Bootstrap GitHub repository
### Synopsis
The bootstrap command creates the GitHub repository if it doesn't exists and
commits the toolkit components manifests to the master branch.
Then it configure the target cluster to synchronize with the repository.
If the toolkit components are present on the cluster,
the bootstrap command will perform an upgrade if needed.
```
tk bootstrap github [flags]
```
### Examples
```
# Create a GitHub personal access token and export it as an env var
export GITHUB_TOKEN=<my-token>
# Run bootstrap for a private repo owned by a GitHub organization
bootstrap github --owner=<organization> --repository=<repo name>
# Run bootstrap for a public repository on a personal account
bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true
# Run bootstrap for a private repo hosted on GitHub Enterprise
bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain>
```
### Options
```
-h, --help help for github
--hostname string GitHub hostname (default "github.com")
--interval duration sync interval (default 1m0s)
--owner string GitHub user or organization name
--personal is personal repository
--private is private repository (default true)
--repository string GitHub repository name
```
### Options inherited from parent commands
```
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller])
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--namespace string the namespace scope for this operation (default "gitops-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
--version string toolkit tag or branch (default "master")
```
### SEE ALSO
* [tk bootstrap](tk_bootstrap.md) - Bootstrap commands
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -44,4 +44,4 @@ tk check [flags]
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -44,4 +44,4 @@ To configure your bash shell to load completions for each session add to your ba
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -9,6 +9,7 @@ Create commands
### Options
```
--export export in yaml format to stdout
-h, --help help for create
--interval duration source sync interval (default 1m0s)
```
@ -29,4 +30,4 @@ Create commands
* [tk create kustomization](tk_create_kustomization.md) - Create or update a kustomization resource
* [tk create source](tk_create_source.md) - Create source commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -66,6 +66,7 @@ tk create kustomization [name] [flags]
```
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller])
--export export in yaml format to stdout
--interval duration source sync interval (default 1m0s)
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--namespace string the namespace scope for this operation (default "gitops-system")
@ -77,4 +78,4 @@ tk create kustomization [name] [flags]
* [tk create](tk_create.md) - Create commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -16,6 +16,7 @@ Create source commands
```
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller])
--export export in yaml format to stdout
--interval duration source sync interval (default 1m0s)
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--namespace string the namespace scope for this operation (default "gitops-system")
@ -28,4 +29,4 @@ Create source commands
* [tk create](tk_create.md) - Create commands
* [tk create source git](tk_create_source_git.md) - Create or update a git source
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -31,11 +31,19 @@ tk create source git [name] [flags]
--url=https://github.com/stefanprodan/podinfo \
--tag-semver=">=3.2.0 <3.3.0"
# Create a source from a Git repository using SSH authentication
# Create a source from a Git repository using SSH authentication
create source git podinfo \
--url=ssh://git@github.com/stefanprodan/podinfo \
--branch=master
# Create a source from a Git repository using SSH authentication and an
# ECDSA P-521 curve public key
create source git podinfo \
--url=ssh://git@github.com/stefanprodan/podinfo \
--branch=master \
--ssh-key-algorithm=ecdsa \
--ssh-ecdsa-curve=p521
# Create a source from a Git repository using basic authentication
create source git podinfo \
--url=https://github.com/stefanprodan/podinfo \
@ -47,19 +55,23 @@ tk create source git [name] [flags]
### Options
```
--branch string git branch (default "master")
-h, --help help for git
-p, --password string basic authentication password
--tag string git tag
--tag-semver string git tag semver range
--url string git address, e.g. ssh://git@host/org/repository
-u, --username string basic authentication username
--branch string git branch (default "master")
-h, --help help for git
-p, --password string basic authentication password
--ssh-ecdsa-curve ecdsaCurve SSH ECDSA public key curve (p521, p256, p384) (default p384)
--ssh-key-algorithm publicKeyAlgorithm SSH public key algorithm (rsa, ecdsa, ed25519) (default rsa)
--ssh-rsa-bits rsaKeyBits SSH RSA public key bit size (multiplies of 8) (default 2048)
--tag string git tag
--tag-semver string git tag semver range
--url string git address, e.g. ssh://git@host/org/repository
-u, --username string basic authentication username
```
### Options inherited from parent commands
```
--components strings list of components, accepts comma-separated values (default [source-controller,kustomize-controller])
--export export in yaml format to stdout
--interval duration source sync interval (default 1m0s)
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--namespace string the namespace scope for this operation (default "gitops-system")
@ -71,4 +83,4 @@ tk create source git [name] [flags]
* [tk create source](tk_create_source.md) - Create source commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -29,4 +29,4 @@ Delete commands
* [tk delete kustomization](tk_delete_kustomization.md) - Delete kustomization
* [tk delete source](tk_delete_source.md) - Delete sources commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -31,4 +31,4 @@ tk delete kustomization [name] [flags]
* [tk delete](tk_delete.md) - Delete commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -28,4 +28,4 @@ Delete sources commands
* [tk delete](tk_delete.md) - Delete commands
* [tk delete source git](tk_delete_source_git.md) - Delete git source
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -31,4 +31,4 @@ tk delete source git [name] [flags]
* [tk delete source](tk_delete_source.md) - Delete sources commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -29,4 +29,4 @@ Export commands
* [tk export kustomization](tk_export_kustomization.md) - Export kustomization in YAML format
* [tk export source](tk_export_source.md) - Export source commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -42,4 +42,4 @@ tk export kustomization [name] [flags]
* [tk export](tk_export.md) - Export commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -29,4 +29,4 @@ Export source commands
* [tk export](tk_export.md) - Export commands
* [tk export source git](tk_export_source_git.md) - Export git sources in YAML format
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -43,4 +43,4 @@ tk export source git [name] [flags]
* [tk export source](tk_export_source.md) - Export source commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -28,4 +28,4 @@ Get commands
* [tk get kustomizations](tk_get_kustomizations.md) - Get kustomizations status
* [tk get sources](tk_get_sources.md) - Get sources commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -31,4 +31,4 @@ tk get kustomizations [flags]
* [tk get](tk_get.md) - Get commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -27,4 +27,4 @@ Get sources commands
* [tk get](tk_get.md) - Get commands
* [tk get sources git](tk_get_sources_git.md) - Get git sources status
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -31,4 +31,4 @@ tk get sources git [flags]
* [tk get sources](tk_get_sources.md) - Get sources commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -49,4 +49,4 @@ tk install [flags]
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -27,4 +27,4 @@ Resume commands
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
* [tk resume kustomization](tk_resume_kustomization.md) - Resume kustomization
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -30,4 +30,4 @@ tk resume kustomization [name] [flags]
* [tk resume](tk_resume.md) - Resume commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -27,4 +27,4 @@ Suspend commands
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
* [tk suspend kustomization](tk_suspend_kustomization.md) - Suspend kustomization
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -30,4 +30,4 @@ tk suspend kustomization [name] [flags]
* [tk suspend](tk_suspend.md) - Suspend commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -28,4 +28,4 @@ Synchronize commands
* [tk sync kustomization](tk_sync_kustomization.md) - Synchronize kustomization
* [tk sync source](tk_sync_source.md) - Synchronize source commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -43,4 +43,4 @@ tk sync kustomization [name] [flags]
* [tk sync](tk_sync.md) - Synchronize commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -27,4 +27,4 @@ Synchronize source commands
* [tk sync](tk_sync.md) - Synchronize commands
* [tk sync source git](tk_sync_source_git.md) - Synchronize git source
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -39,4 +39,4 @@ tk sync source git [name] [flags]
* [tk sync source](tk_sync_source.md) - Synchronize source commands
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -46,4 +46,4 @@ tk uninstall [flags]
* [tk](tk.md) - Command line utility for assembling Kubernetes CD pipelines
###### Auto generated by spf13/cobra on 5-May-2020
###### Auto generated by spf13/cobra on 9-Jun-2020

@ -6,6 +6,8 @@ require (
github.com/blang/semver v3.5.1+incompatible
github.com/fluxcd/kustomize-controller v0.0.1-beta.1
github.com/fluxcd/source-controller v0.0.1-beta.1
github.com/go-git/go-git/v5 v5.0.0
github.com/google/go-github/v32 v32.0.0
github.com/manifoldco/promptui v0.7.0
github.com/spf13/cobra v1.0.0
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073

@ -48,13 +48,16 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@ -92,6 +95,7 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.2 h1:ForxmXkA6tPIvffbrDAcPUIB32QgXkt2XFj+F0UxetA=
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=
@ -122,6 +126,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/deislabs/oras v0.8.1 h1:If674KraJVpujYR00rzdi0QAmW4BxzMJPVAZJKuhQ0c=
github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@ -169,6 +174,7 @@ github.com/fluxcd/source-controller v0.0.1-alpha.6 h1:CpSH1mA9bRjifRwmcVS98ejY2M
github.com/fluxcd/source-controller v0.0.1-alpha.6/go.mod h1:gvU+sR6yH9kbyWZAJ9NEBQJMsJ+S3yCyOdPIhM+8FUI=
github.com/fluxcd/source-controller v0.0.1-beta.1 h1:1lNFrAwnrZG2qWbm9/6qgDsY4F6go+6HZ4XSCmmpAiY=
github.com/fluxcd/source-controller v0.0.1-beta.1/go.mod h1:tmscNdCxEt7+Xt2g1+bI38hMPw2leYMFAaCn4UlMGuw=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -176,6 +182,7 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@ -186,6 +193,7 @@ github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc=
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg=
github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA=
@ -313,6 +321,10 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github/v32 v32.0.0 h1:q74KVb22spUq0U5HqZ9VCYqQz8YRuOtL/39ZnfwO+NM=
github.com/google/go-github/v32 v32.0.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
@ -481,8 +493,10 @@ github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@ -705,6 +719,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -793,6 +808,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@ -801,6 +817,7 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=

Loading…
Cancel
Save