Skip to content

Commit

Permalink
Merge "CLI: add dev cloneAsAdmin subcommand"
Browse files Browse the repository at this point in the history
  • Loading branch information
Microzuul CI authored and Gerrit Code Review committed Jan 26, 2024
2 parents 2e7f078 + fef6c07 commit 388397d
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 36 deletions.
31 changes: 26 additions & 5 deletions cli/cmd/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,35 @@ func devWipe(kmd *cobra.Command, args []string) {
}
}

func devCloneAsAdmin(kmd *cobra.Command, args []string) {}
func devCloneAsAdmin(kmd *cobra.Command, args []string) {
cliCtx := cliutils.GetCLIctxOrDie(kmd, args, []string{})
repoName := args[0]
var dest string
if len(args) > 1 {
dest = args[1]
} else {
dest = "."
}
ns := cliCtx.Namespace
kubeContext := cliCtx.KubeContext
fqdn := cliCtx.FQDN
verify, _ := kmd.Flags().GetBool("verify")
env := cliutils.ENV{
Cli: cliutils.CreateKubernetesClientOrDie(kubeContext),
Ctx: context.TODO(),
Ns: ns,
}
gerrit.CloneAsAdmin(&env, fqdn, repoName, dest, verify)
}

func devRunTests(kmd *cobra.Command, args []string) {}

func MkDevCmd() *cobra.Command {

var (
deleteData bool
devCmd = &cobra.Command{
deleteData bool
verifyCloneSSL bool
devCmd = &cobra.Command{
Use: "dev",
Short: "development subcommands",
Long: "These subcommands can be used to manage a dev environment and streamline recurrent development tasks like running the operator's test suite.",
Expand All @@ -95,19 +115,20 @@ func MkDevCmd() *cobra.Command {
Run: devWipe,
}
cloneAsAdminCmd = &cobra.Command{
Use: "clone-as-admin REPO DEST",
Use: "cloneAsAdmin REPO [DEST]",
Long: "Clone a repo hosted on the dev code review system as an admin user.",
Run: devCloneAsAdmin,
}
runTestsCmd = &cobra.Command{
Use: "run-tests TESTNAME",
Use: "runTests TESTNAME",
Long: "Wipe a development resource. The resource can be a gerrit instance.",
ValidArgs: devRunTestsAllowedArgs,
Run: devRunTests,
}
)
// args
wipeCmd.Flags().BoolVar(&deleteData, "rm-data", false, "Delete also persistent data. This will result in data loss, like review history.")
cloneAsAdminCmd.Flags().BoolVar(&verifyCloneSSL, "verify", false, "Verify SSL endpoint")

devCmd.AddCommand(createCmd)
devCmd.AddCommand(wipeCmd)
Expand Down
69 changes: 69 additions & 0 deletions cli/cmd/dev/gerrit/gerrit.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"os"
"path/filepath"
"time"

_ "embed"
Expand Down Expand Up @@ -476,3 +477,71 @@ func WipeGerrit(env *cliutils.ENV, rmData bool) {
cliutils.DeleteOrDie(env, &apiv1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "gerrit-gerrit-0", Namespace: ns}})
}
}

func GetAdminRepoURL(env *cliutils.ENV, fqdn string, repoName string) string {
var (
gerritAPIKey apiv1.Secret
)
if !cliutils.GetMOrDie(env, "gerrit-admin-api-key", &gerritAPIKey) {
ctrl.Log.Error(errors.New("secret 'gerrit-admin-api-key' does not exist"), "Cannot clone repo as admin")
os.Exit(1)
}
apiKey := string(gerritAPIKey.Data["gerrit-admin-api-key"])
ctrl.Log.V(5).Info("API Key: " + apiKey)
repoURL := fmt.Sprintf("https://admin:%s@gerrit.%s/a/%s", apiKey, fqdn, repoName)
return repoURL
}

func CloneAsAdmin(env *cliutils.ENV, fqdn string, repoName string, dest string, verify bool) {
var (
output string
)
repoURL := GetAdminRepoURL(env, fqdn, repoName)
if _, err := os.Stat(filepath.Join(dest, ".git")); os.IsNotExist(err) {
ctrl.Log.Info("Cloning repo at: " + repoURL)
args := []string{}
if !verify {
args = append(args, "-c", "http.sslVerify=false")
}
args = append(args, "clone", repoURL, dest)
output = cliutils.RunCmdOrDie("git", args...)
ctrl.Log.V(5).Info("captured output:\n" + output)
output = cliutils.RunCmdOrDie("git", "-C", dest, "remote", "add", "gerrit", repoURL)
ctrl.Log.V(5).Info("captured output:\n" + output)
} else {
ctrl.Log.Info("Repository exists. Resetting remotes...")
for _, o := range []string{
cliutils.RunCmdOrDie("git", "-C", dest, "remote", "set-url", "origin", repoURL),
cliutils.RunCmdOrDie("git", "-C", dest, "remote", "set-url", "gerrit", repoURL),
cliutils.RunCmdOrDie("git", "-C", dest, "fetch", "origin"),
} {
if o != "" {
ctrl.Log.V(5).Info("captured output:\n" + o)
}
}
}
ctrl.Log.Info("Configuring local repository for commits...")
for _, _args := range [][]string{
{
"-C", dest, "config", "user.email", "admin@" + fqdn,
},
{
"-C", dest, "config", "user.name", "admin",
},
{
"-C", dest, "reset", "--hard", "origin/master",
},
} {
output = cliutils.RunCmdOrDie("git", _args...)
if output != "" {
ctrl.Log.V(5).Info("captured output:\n" + output)
}
}
if !verify {
output = cliutils.RunCmdOrDie("git",
"-C", dest, "config", "http.sslverify", "false")
if output != "" {
ctrl.Log.V(5).Info("captured output:\n" + output)
}
}
}
42 changes: 32 additions & 10 deletions cli/cmd/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"os"
"os/exec"
"reflect"
"strings"

Expand Down Expand Up @@ -258,18 +259,23 @@ func GetCLIctxOrDie(kmd *cobra.Command, args []string, allowedArgs []string) Sof
ctrl.Log.Error(err, "Error initializing:")
os.Exit(1)
}
argumentError := errors.New("argument must be in: " + strings.Join(allowedArgs, ", "))
if len(args) != 1 {
ctrl.Log.Error(argumentError, "Need one argument")
os.Exit(1)
}
for _, a := range allowedArgs {
if args[0] == a {
return cliCtx
if len(allowedArgs) == 0 {
// no more validation needed
return cliCtx
} else {
argumentError := errors.New("argument must be in: " + strings.Join(allowedArgs, ", "))
if len(args) != 1 {
ctrl.Log.Error(argumentError, "Need one argument")
os.Exit(1)
}
for _, a := range allowedArgs {
if args[0] == a {
return cliCtx
}
}
ctrl.Log.Error(argumentError, "Unknown argument "+args[0])
os.Exit(1)
}
ctrl.Log.Error(argumentError, "Unknown argument "+args[0])
os.Exit(1)
return SoftwareFactoryConfigContext{}
}

Expand All @@ -287,3 +293,19 @@ func GetFileContent(filePath string) ([]byte, error) {
return nil, err
}
}

func RunCmdWithEnvOrDie(environ []string, cmd string, args ...string) string {
kmd := exec.Command(cmd, args...)
kmd.Env = append(os.Environ(), environ...)
out, err := kmd.CombinedOutput()
if err != nil {
ctrl.Log.Error(err, "Could not run command '"+cmd+"'")
ctrl.Log.Info("Captured output:\n" + string(out))
os.Exit(1)
}
return string(out)
}

func RunCmdOrDie(cmd string, args ...string) string {
return RunCmdWithEnvOrDie([]string{}, cmd, args...)
}
32 changes: 11 additions & 21 deletions cli/sfconfig/cmd/dev/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,18 @@ func EnsureDemoConfig(env *utils.ENV, sfconfig *config.SFConfig, updateDemoTenan
configRepoPath = "deploy/config"
demoConfigRepoPath = "deploy/demo-tenant-config"
)
apiKey := string(utils.GetSecret(env, "gerrit-admin-api-key"))
gEnv := cliutils.ENV{
Cli: env.Cli,
Ns: env.Ns,
Ctx: env.Ctx,
}
fmt.Println("[+] Ensuring demo config")
EnsureRepo(sfconfig, apiKey, "config")
EnsureRepo(sfconfig, apiKey, "demo-tenant-config")
EnsureRepo(sfconfig, apiKey, "demo-project")
for _, repo := range []string{
"config", "demo-tenant-config", "demo-project",
} {
path := filepath.Join("deploy", repo)
cligerrit.CloneAsAdmin(&gEnv, sfconfig.FQDN, repo, path, false)
}
setupDemoTenantConfigRepo(demoConfigRepoPath)
PushRepoIfNeeded(demoConfigRepoPath)
if updateDemoTenantDefinition {
Expand Down Expand Up @@ -174,23 +181,6 @@ func EnsureGerritAccess(fqdn string) {
}
}

func EnsureRepo(sfconfig *config.SFConfig, apiKey string, name string) {
path := filepath.Join("deploy", name)
origin := fmt.Sprintf("https://admin:%s@gerrit.%s/a/%s", apiKey, sfconfig.FQDN, name)
if _, err := os.Stat(filepath.Join(path, ".git")); os.IsNotExist(err) {
utils.RunCmd("git", "-c", "http.sslVerify=false", "clone", origin, path)
utils.RunCmd("git", "-C", path, "remote", "add", "gerrit", origin)
} else {
utils.RunCmd("git", "-C", path, "remote", "set-url", "origin", origin)
utils.RunCmd("git", "-C", path, "remote", "set-url", "gerrit", origin)
utils.RunCmd("git", "-C", path, "fetch", "origin")
}
utils.RunCmd("git", "-C", path, "config", "http.sslverify", "false")
utils.RunCmd("git", "-C", path, "config", "user.email", "admin@"+sfconfig.FQDN)
utils.RunCmd("git", "-C", path, "config", "user.name", "admin")
utils.RunCmd("git", "-C", path, "reset", "--hard", "origin/master")
}

func EnsureCRD() {
// TODO: implement natively and avoir re-entry
fmt.Println("[+] Installing CRD...")
Expand Down
19 changes: 19 additions & 0 deletions doc/reference/cli/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ deployments, beyond what can be defined in a custom resource manifest.
1. [Configuration File](#configuration-file)
1. [Subcommands](#subcommands)
1. [Dev](#dev)
1. [cloneAsAdmin](#cloneasadmin)
1. [create gerrit](#create-gerrit)
1. [wipe gerrit](#wipe-gerrit)
1. [Nodepool](#nodepool)
Expand Down Expand Up @@ -104,6 +105,24 @@ default-context: dev
The `dev` subcommand can be used to manage a development environment and run tests.

### cloneAsAdmin

> ⚠️ A Gerrit instance must have been deployed with the [create gerrit](#create-gerrit) command first.

Clone a given repository hosted on the Gerrit instance, as the admin user. You can then proceed to
create patches and run them through CI with `git review`. If the repository already exists locally,
refresh it by resetting the remotes and performing a [hard reset](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---hard) on the master branch.

```sh
go run ./main.go [GLOBAL FLAGS] cloneAsAdmin REPO [DEST] [flags]
```

Flags:

| Argument | Type | Description | Optional | Default |
|----------|------|-------|----|----|
| --verify | boolean | Enforce SSL validation | yes | False |

### create gerrit

Create a Gerrit stateful set that can be used to host repositories and code reviews with a SF deployment.
Expand Down

0 comments on commit 388397d

Please sign in to comment.