diff --git a/cmd/tk/bootstrap_github.go b/cmd/tk/bootstrap_github.go index 6fd12dab..706135d4 100644 --- a/cmd/tk/bootstrap_github.go +++ b/cmd/tk/bootstrap_github.go @@ -56,13 +56,19 @@ var ( ghPrivate bool ) -const ghTokenName = "GITHUB_TOKEN" +const ( + ghTokenName = "GITHUB_TOKEN" + ghBranch = "master" + ghInstallManifest = "toolkit.yaml" + ghSourceManifest = "toolkit-source.yaml" + ghKustomizationManifest = "toolkit-kustomization.yaml" +) 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, "personal repository") - bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "private repository") + 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") bootstrapCmd.AddCommand(bootstrapGitHubCmd) } @@ -94,12 +100,12 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { // create GitHub repository if doesn't exists logAction("connecting to GitHub") - if err := initGitHubRepository(ctx, ghOwner, ghRepository, ghToken, ghPrivate, ghPersonal); err != nil { + if err := createGitHubRepository(ctx, ghOwner, ghRepository, ghToken, ghPrivate, ghPersonal); err != nil { return err } // clone repository and checkout the master branch - repo, err := checkoutGitHubRepository(ctx, tmpDir, ghURL, ghToken) + repo, err := checkoutGitHubRepository(ctx, ghURL, ghBranch, ghToken, tmpDir) if err != nil { return err } @@ -118,8 +124,8 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { return err } + // push install manifests if changed { - // push install manifests if err := pushGitHubRepository(ctx, repo, ghToken); err != nil { return err } @@ -128,6 +134,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { logSuccess("components are up to date") } + // determine if repo synchronization is working isInstall := shouldInstallGitHub(ctx, kubeClient, namespace) if isInstall { @@ -139,7 +146,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { } logSuccess("install completed") - // check rollout status + // check installation logWaiting("verifying installation") for _, deployment := range components { command = fmt.Sprintf("kubectl -n %s rollout status deployment %s --timeout=%s", @@ -153,14 +160,16 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { } // create or update auth secret + // TODO: replace this with SSH deploy key if err := generateBasicAuth(ctx, namespace, namespace, "git", ghToken); err != nil { return err } logSuccess("authentication configured") - // generate and push source kustomization + // configure repo synchronization if isInstall { - logAction("generating kustomization manifests") + // generate source and kustomization manifests + logAction("generating sync manifests") if err := generateGitHubKustomization(ghURL, namespace, namespace, tmpDir, ghInterval); err != nil { return err } @@ -171,15 +180,16 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { return err } - // push install manifests + // push manifests if changed { if err := pushGitHubRepository(ctx, repo, ghToken); err != nil { return err } } - logSuccess("kustomization manifests pushed") + logSuccess("sync manifests pushed") - logAction("applying kustomization manifests") + // apply manifests and waiting for sync + logAction("applying sync manifests") if err := applyGitHubKustomization(ctx, kubeClient, namespace, namespace, tmpDir); err != nil { return err } @@ -189,20 +199,24 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { return nil } -func initGitHubRepository(ctx context.Context, owner, name, token string, isPrivate, isPersonal bool) error { +func createGitHubRepository(ctx context.Context, owner, name, token string, isPrivate, isPersonal bool) error { autoInit := true auth := github.BasicAuthTransport{ Username: "git", Password: token, } + gh := github.NewClient(auth.Client()) org := "" if !isPersonal { org = owner } - client := github.NewClient(auth.Client()) - _, _, err := client.Repositories.Create(ctx, org, &github.Repository{ + if _, _, err := gh.Repositories.Get(ctx, org, name); err == nil { + return nil + } + + _, _, err := gh.Repositories.Create(ctx, org, &github.Repository{ AutoInit: &autoInit, Name: &name, Private: &isPrivate, @@ -217,8 +231,7 @@ func initGitHubRepository(ctx context.Context, owner, name, token string, isPriv return nil } -func checkoutGitHubRepository(ctx context.Context, path, url, token string) (*git.Repository, error) { - branch := "master" +func checkoutGitHubRepository(ctx context.Context, url, branch, token, path string) (*git.Repository, error) { auth := &http.BasicAuth{ Username: "git", Password: token, @@ -246,14 +259,14 @@ func checkoutGitHubRepository(ctx context.Context, path, url, token string) (*gi } func generateGitHubInstall(namespace, tmpDir string) (string, error) { - kDir := path.Join(tmpDir, ".kustomization") - defer os.RemoveAll(kDir) + tkDir := path.Join(tmpDir, ".tk") + defer os.RemoveAll(tkDir) - if err := os.MkdirAll(kDir, os.ModePerm); err != nil { + if err := os.MkdirAll(tkDir, os.ModePerm); err != nil { return "", fmt.Errorf("generating manifests failed: %w", err) } - if err := genInstallManifests(bootstrapVersion, namespace, components, kDir); err != nil { + if err := genInstallManifests(bootstrapVersion, namespace, components, tkDir); err != nil { return "", fmt.Errorf("generating manifests failed: %w", err) } @@ -262,8 +275,8 @@ func generateGitHubInstall(namespace, tmpDir string) (string, error) { return "", fmt.Errorf("generating manifests failed: %w", err) } - manifest := path.Join(manifestsDir, "toolkit.yaml") - if err := buildKustomization(kDir, manifest); err != nil { + manifest := path.Join(manifestsDir, ghInstallManifest) + if err := buildKustomization(tkDir, manifest); err != nil { return "", fmt.Errorf("build kustomization failed: %w", err) } @@ -290,7 +303,7 @@ func commitGitHubManifests(repo *git.Repository, namespace string) (bool, error) if _, err := w.Commit("Add manifests", &git.CommitOptions{ Author: &object.Signature{ Name: "tk", - Email: "tk@@users.noreply.github.com", + Email: "tk@users.noreply.github.com", When: time.Now(), }, }); err != nil { @@ -347,7 +360,7 @@ func generateGitHubKustomization(url, name, namespace, tmpDir string, interval t return err } - if err := utils.writeFile(string(gitData), filepath.Join(tmpDir, namespace, "toolkit-source.yaml")); err != nil { + if err := utils.writeFile(string(gitData), filepath.Join(tmpDir, namespace, ghSourceManifest)); err != nil { return err } @@ -381,7 +394,7 @@ func generateGitHubKustomization(url, name, namespace, tmpDir string, interval t return err } - if err := utils.writeFile(string(ksData), filepath.Join(tmpDir, namespace, "toolkit-kustomization.yaml")); err != nil { + if err := utils.writeFile(string(ksData), filepath.Join(tmpDir, namespace, ghKustomizationManifest)); err != nil { return err } @@ -394,7 +407,7 @@ func applyGitHubKustomization(ctx context.Context, kubeClient client.Client, nam return err } - logWaiting("waiting for kustomization sync") + logWaiting("waiting for cluster sync") if err := wait.PollImmediate(pollInterval, timeout, isKustomizationReady(ctx, kubeClient, name, namespace)); err != nil { return err