feat: Application generation strategies and clusters generation (#8263)

feat: Application generation strategies and clusters generation (#8263)

Signed-off-by: pashavictorovich <[email protected]>
This commit is contained in:
pasha-codefresh
2022-01-24 09:24:39 -08:00
committed by GitHub
parent ce1690a925
commit aab12edc26
17 changed files with 589 additions and 338 deletions
-76
View File
@@ -1,76 +0,0 @@
package commands
import (
"log"
"os"
generator "github.com/argoproj/argo-cd/v2/hack/gen-resources/generators"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/tools"
"github.com/spf13/cobra"
)
func NewAllResourcesCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "all",
Short: "Manage all resources",
Long: "Manage all resources",
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
os.Exit(1)
},
}
command.AddCommand(NewAllResourcesGenerationCommand(opts))
command.AddCommand(NewAllResourcesCleanCommand(opts))
return command
}
func NewAllResourcesGenerationCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "generate",
Short: "Generate all resources",
Long: "Generate all resources",
Run: func(c *cobra.Command, args []string) {
clientSet := tools.ConnectToK8sArgoClientSet()
pg := generator.NewProjectGenerator(clientSet)
ag := generator.NewApplicationGenerator(clientSet)
rg := generator.NewRepoGenerator(tools.ConnectToK8sClientSet())
err := pg.Generate(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
err = ag.Generate(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
err = rg.Generate(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
command.PersistentFlags().IntVar(&opts.Samples, "samples", 1, "Amount of samples")
return command
}
func NewAllResourcesCleanCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "clean",
Short: "Clean all resources",
Long: "Clean all resources",
Run: func(c *cobra.Command, args []string) {
clientSet := tools.ConnectToK8sArgoClientSet()
pg := generator.NewProjectGenerator(clientSet)
ag := generator.NewApplicationGenerator(clientSet)
err := pg.Clean(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
err = ag.Clean(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
return command
}
@@ -1,59 +0,0 @@
package commands
import (
"log"
"os"
generator "github.com/argoproj/argo-cd/v2/hack/gen-resources/generators"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/tools"
"github.com/spf13/cobra"
)
func NewApplicationCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "application",
Short: "Manage applications",
Long: "Manage applications",
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
os.Exit(1)
},
}
command.AddCommand(NewApplicationGenerationCommand(opts))
command.AddCommand(NewApplicationCleanCommand(opts))
return command
}
func NewApplicationGenerationCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "generate",
Short: "Generate applications",
Long: "Generate applications",
Run: func(c *cobra.Command, args []string) {
pg := generator.NewApplicationGenerator(tools.ConnectToK8sArgoClientSet())
err := pg.Generate(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
command.PersistentFlags().IntVar(&opts.Samples, "samples", 1, "Amount of samples")
return command
}
func NewApplicationCleanCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "clean",
Short: "Clean applications",
Long: "Clean applications",
Run: func(c *cobra.Command, args []string) {
pg := generator.NewApplicationGenerator(tools.ConnectToK8sArgoClientSet())
err := pg.Clean(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
return command
}
+132
View File
@@ -0,0 +1,132 @@
package commands
import (
"context"
"log"
"github.com/spf13/cobra"
generator "github.com/argoproj/argo-cd/v2/hack/gen-resources/generators"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/settings"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/util"
"github.com/argoproj/argo-cd/v2/util/cli"
)
const (
cliName = "argocd-generator"
)
func init() {
cobra.OnInitialize(initConfig)
}
func initConfig() {
cli.SetLogFormat(cmdutil.LogFormat)
cli.SetLogLevel(cmdutil.LogLevel)
}
// NewCommand returns a new instance of an argocd command
func NewCommand() *cobra.Command {
var generateOpts util.GenerateOpts
var command = &cobra.Command{
Use: cliName,
Short: "Generator for argocd resources",
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
},
DisableAutoGenTag: true,
}
command.AddCommand(NewGenerateCommand(&generateOpts))
command.AddCommand(NewCleanCommand(&generateOpts))
command.PersistentFlags().StringVar(&generateOpts.Namespace, "kube-namespace", "argocd", "Name of the namespace on which Argo agent should be installed [$KUBE_NAMESPACE]")
return command
}
func NewGenerateCommand(opts *util.GenerateOpts) *cobra.Command {
var file string
var command = &cobra.Command{
Use: "generate [-f file]",
Short: "Generate entities",
Long: "Generate entities",
Run: func(c *cobra.Command, args []string) {
log.Printf("Retrieve configuration from %s", file)
err := util.Parse(opts, file)
if err != nil {
log.Fatalf("Failed to retrieve configuration, %v", err.Error())
}
argoClientSet := util.ConnectToK8sArgoClientSet()
clientSet := util.ConnectToK8sClientSet()
settingsMgr := settings.NewSettingsManager(context.TODO(), clientSet, opts.Namespace)
argoDB := db.NewDB(opts.Namespace, settingsMgr, clientSet)
pg := generator.NewProjectGenerator(argoClientSet)
ag := generator.NewApplicationGenerator(argoClientSet, clientSet, argoDB)
rg := generator.NewRepoGenerator(util.ConnectToK8sClientSet())
cg := generator.NewClusterGenerator(argoDB, util.ConnectToK8sClientSet(), util.ConnectToK8sConfig())
err = pg.Generate(opts)
if err != nil {
log.Fatalf("Failed to generate projects, %v", err.Error())
}
err = rg.Generate(opts)
if err != nil {
log.Fatalf("Failed to generate repositories, %v", err.Error())
}
err = cg.Generate(opts)
if err != nil {
log.Fatalf("Failed to generate clusters, %v", err.Error())
}
err = ag.Generate(opts)
if err != nil {
log.Fatalf("Failed to generate applications, %v", err.Error())
}
},
}
command.Flags().StringVarP(&file, "file", "f", "", "")
return command
}
func NewCleanCommand(opts *util.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "clean",
Short: "Clean entities",
Long: "Clean entities",
Run: func(c *cobra.Command, args []string) {
argoClientSet := util.ConnectToK8sArgoClientSet()
clientSet := util.ConnectToK8sClientSet()
settingsMgr := settings.NewSettingsManager(context.TODO(), clientSet, opts.Namespace)
argoDB := db.NewDB(opts.Namespace, settingsMgr, clientSet)
pg := generator.NewProjectGenerator(argoClientSet)
ag := generator.NewApplicationGenerator(argoClientSet, clientSet, argoDB)
cg := generator.NewClusterGenerator(argoDB, clientSet, util.ConnectToK8sConfig())
rg := generator.NewRepoGenerator(clientSet)
err := pg.Clean(opts)
if err != nil {
log.Fatalf("Failed to clean projects, %v", err.Error())
}
err = ag.Clean(opts)
if err != nil {
log.Fatalf("Failed to clean applications, %v", err.Error())
}
err = cg.Clean(opts)
if err != nil {
log.Fatalf("Failed to clean clusters, %v", err.Error())
}
err = rg.Clean(opts)
if err != nil {
log.Fatalf("Failed to clean repositores, %v", err.Error())
}
},
}
return command
}
@@ -1,60 +0,0 @@
package commands
import (
"log"
"os"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/tools"
generator "github.com/argoproj/argo-cd/v2/hack/gen-resources/generators"
"github.com/spf13/cobra"
)
func NewProjectCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "project",
Short: "Manage projects",
Long: "Manage projects",
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
os.Exit(1)
},
}
command.AddCommand(NewProjectGenerationCommand(opts))
command.AddCommand(NewProjectCleanCommand(opts))
return command
}
func NewProjectGenerationCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "generate",
Short: "Generate projects",
Long: "Generate projects",
Run: func(c *cobra.Command, args []string) {
pg := generator.NewProjectGenerator(tools.ConnectToK8sArgoClientSet())
err := pg.Generate(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
command.PersistentFlags().IntVar(&opts.Samples, "samples", 1, "Amount of samples")
return command
}
func NewProjectCleanCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "clean",
Short: "Clean projects",
Long: "Clean projects",
Run: func(c *cobra.Command, args []string) {
pg := generator.NewProjectGenerator(tools.ConnectToK8sArgoClientSet())
err := pg.Clean(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
return command
}
-61
View File
@@ -1,61 +0,0 @@
package commands
import (
"log"
"os"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/tools"
generator "github.com/argoproj/argo-cd/v2/hack/gen-resources/generators"
"github.com/spf13/cobra"
)
func NewReposCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "repos",
Short: "Manage repos",
Long: "Manage repos",
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
os.Exit(1)
},
}
command.AddCommand(NewReposGenerationCommand(opts))
command.AddCommand(NewReposCleanCommand(opts))
return command
}
func NewReposGenerationCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "generate",
Short: "Generate repos",
Long: "Generate repos",
Run: func(c *cobra.Command, args []string) {
rg := generator.NewRepoGenerator(tools.ConnectToK8sClientSet())
err := rg.Generate(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
command.PersistentFlags().StringVar(&opts.GithubToken, "token", "", "Github token")
command.PersistentFlags().IntVar(&opts.Samples, "samples", 1, "Amount of samples")
return command
}
func NewReposCleanCommand(opts *generator.GenerateOpts) *cobra.Command {
var command = &cobra.Command{
Use: "clean",
Short: "Clean repos",
Long: "Clean repos",
Run: func(c *cobra.Command, args []string) {
pg := generator.NewRepoGenerator(tools.ConnectToK8sClientSet())
err := pg.Clean(opts)
if err != nil {
log.Fatalf("Something went wrong, %v", err.Error())
}
},
}
return command
}
-42
View File
@@ -1,42 +0,0 @@
package commands
import (
"github.com/spf13/cobra"
generator "github.com/argoproj/argo-cd/v2/hack/gen-resources/generators"
cmdutil "github.com/argoproj/argo-cd/v2/cmd/util"
"github.com/argoproj/argo-cd/v2/util/cli"
)
const (
cliName = "argocd-generator"
)
func init() {
cobra.OnInitialize(initConfig)
}
func initConfig() {
cli.SetLogFormat(cmdutil.LogFormat)
cli.SetLogLevel(cmdutil.LogLevel)
}
// NewCommand returns a new instance of an argocd command
func NewCommand() *cobra.Command {
var generateOpts generator.GenerateOpts
var command = &cobra.Command{
Use: cliName,
Short: "Generator for argocd resources",
Run: func(c *cobra.Command, args []string) {
c.HelpFunc()(c, args)
},
DisableAutoGenTag: true,
}
command.AddCommand(NewProjectCommand(&generateOpts))
command.AddCommand(NewApplicationCommand(&generateOpts))
command.AddCommand(NewAllResourcesCommand(&generateOpts))
command.AddCommand(NewReposCommand(&generateOpts))
command.PersistentFlags().StringVar(&generateOpts.Namespace, "kube-namespace", "argocd", "Name of the namespace on which Argo agent should be installed [$KUBE_NAMESPACE]")
return command
}
@@ -0,0 +1,22 @@
application:
samples: 300
source:
strategy: Random
destination:
strategy: Random
cluster:
samples: 2
namespacePrefix: vcluster
valuesFilePath: /Users/argocd/.kube/util/values.yaml
destinationNamespace: argocd
clusterNamePrefix: test
repository:
samples: 100
project:
samples: 15
namespace: argocd
@@ -2,41 +2,103 @@ package generator
import (
"context"
"log"
"math/rand"
"time"
"github.com/argoproj/argo-cd/v2/util/settings"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/util"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
)
type ApplicationGenerator struct {
clientSet *appclientset.Clientset
argoClientSet *appclientset.Clientset
clientSet *kubernetes.Clientset
db db.ArgoDB
}
func NewApplicationGenerator(clientSet *appclientset.Clientset) Generator {
return &ApplicationGenerator{clientSet}
func NewApplicationGenerator(argoClientSet *appclientset.Clientset, clientSet *kubernetes.Clientset, db db.ArgoDB) Generator {
return &ApplicationGenerator{argoClientSet, clientSet, db}
}
func (pg *ApplicationGenerator) Generate(opts *GenerateOpts) error {
applications := pg.clientSet.ArgoprojV1alpha1().Applications(opts.Namespace)
for i := 0; i < opts.Samples; i++ {
_, err := applications.Create(context.TODO(), &v1alpha1.Application{
func (pg *ApplicationGenerator) buildRandomSource(repositories []*v1alpha1.Repository) (*v1alpha1.ApplicationSource, error) {
rand.Seed(time.Now().Unix())
repoNumber := rand.Int() % len(repositories)
return &v1alpha1.ApplicationSource{
RepoURL: repositories[repoNumber].Repo,
Path: "helm-guestbook",
TargetRevision: "master",
}, nil
}
func (ag *ApplicationGenerator) buildSource(opts *util.GenerateOpts, repositories []*v1alpha1.Repository) (*v1alpha1.ApplicationSource, error) {
switch opts.ApplicationOpts.SourceOpts.Strategy {
case "Random":
return ag.buildRandomSource(repositories)
}
return ag.buildRandomSource(repositories)
}
func (pg *ApplicationGenerator) buildRandomDestination(opts *util.GenerateOpts, clusters []v1alpha1.Cluster) (*v1alpha1.ApplicationDestination, error) {
rand.Seed(time.Now().Unix())
clusterNumber := rand.Int() % len(clusters)
return &v1alpha1.ApplicationDestination{
Namespace: opts.Namespace,
Name: clusters[clusterNumber].Name,
}, nil
}
func (ag *ApplicationGenerator) buildDestination(opts *util.GenerateOpts, clusters []v1alpha1.Cluster) (*v1alpha1.ApplicationDestination, error) {
switch opts.ApplicationOpts.DestinationOpts.Strategy {
case "Random":
return ag.buildRandomDestination(opts, clusters)
}
return ag.buildRandomDestination(opts, clusters)
}
func (pg *ApplicationGenerator) Generate(opts *util.GenerateOpts) error {
settingsMgr := settings.NewSettingsManager(context.TODO(), pg.clientSet, opts.Namespace)
repositories, err := db.NewDB(opts.Namespace, settingsMgr, pg.clientSet).ListRepositories(context.TODO())
if err != nil {
return err
}
clusters, err := db.NewDB(opts.Namespace, settingsMgr, pg.clientSet).ListClusters(context.TODO())
if err != nil {
return err
}
applications := pg.argoClientSet.ArgoprojV1alpha1().Applications(opts.Namespace)
for i := 0; i < opts.ApplicationOpts.Samples; i++ {
log.Printf("Generate application #%v", i)
source, err := pg.buildSource(opts, repositories)
if err != nil {
return err
}
log.Printf("Pick source \"%s\"", source)
destination, err := pg.buildDestination(opts, clusters.Items)
if err != nil {
return err
}
log.Printf("Pick destination \"%s\"", destination)
log.Printf("Create application")
_, err = applications.Create(context.TODO(), &v1alpha1.Application{
ObjectMeta: v1.ObjectMeta{
GenerateName: "application-",
Namespace: opts.Namespace,
Labels: labels,
},
Spec: v1alpha1.ApplicationSpec{
Project: "default",
Destination: v1alpha1.ApplicationDestination{
Namespace: opts.Namespace,
Name: "in-cluster",
},
Source: v1alpha1.ApplicationSource{
RepoURL: "https://github.com/argoproj/argocd-example-apps",
Path: "helm-guestbook",
TargetRevision: "master",
},
Project: "default",
Destination: *destination,
Source: *source,
},
}, v1.CreateOptions{})
if err != nil {
@@ -46,8 +108,9 @@ func (pg *ApplicationGenerator) Generate(opts *GenerateOpts) error {
return nil
}
func (ag *ApplicationGenerator) Clean(opts *GenerateOpts) error {
applications := ag.clientSet.ArgoprojV1alpha1().Applications(opts.Namespace)
func (ag *ApplicationGenerator) Clean(opts *util.GenerateOpts) error {
log.Printf("Clean applications")
applications := ag.argoClientSet.ArgoprojV1alpha1().Applications(opts.Namespace)
return applications.DeleteCollection(context.TODO(), v1.DeleteOptions{}, v1.ListOptions{
LabelSelector: "app.kubernetes.io/generated-by=argocd-generator",
})
@@ -0,0 +1,235 @@
package generator
import (
"bytes"
"context"
"encoding/base64"
"log"
"strings"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/util/helm"
"gopkg.in/yaml.v2"
"k8s.io/client-go/kubernetes/scheme"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/remotecommand"
"k8s.io/client-go/kubernetes"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/util"
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/db"
)
const POD_PREFIX = "vcluster"
type Cluster struct {
Server string `yaml:"server"`
CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"`
}
type AuthInfo struct {
ClientCertificateData string `yaml:"client-certificate-data,omitempty"`
ClientKeyData string `yaml:"client-key-data,omitempty"`
}
type NamedCluster struct {
// Name is the nickname for this Cluster
Name string `yaml:"name"`
// Cluster holds the cluster information
Cluster Cluster `yaml:"cluster"`
}
type NamedAuthInfo struct {
// Name is the nickname for this AuthInfo
Name string `yaml:"name"`
// AuthInfo holds the auth information
AuthInfo AuthInfo `yaml:"user"`
}
type Config struct {
Clusters []NamedCluster `yaml:"clusters"`
AuthInfos []NamedAuthInfo `yaml:"users"`
}
type ClusterGenerator struct {
db db.ArgoDB
clientSet *kubernetes.Clientset
config *rest.Config
}
func NewClusterGenerator(db db.ArgoDB, clientSet *kubernetes.Clientset, config *rest.Config) Generator {
return &ClusterGenerator{db, clientSet, config}
}
func (cg *ClusterGenerator) getClusterCredentials(namespace string, releaseSuffix string) ([]byte, []byte, []byte, error) {
cmd := []string{
"sh",
"-c",
"cat /root/.kube/config",
}
var stdout, stderr, stdin bytes.Buffer
option := &v1.PodExecOptions{
Command: cmd,
Container: "syncer",
Stdin: true,
Stdout: true,
Stderr: true,
TTY: true,
}
req := cg.clientSet.CoreV1().RESTClient().Post().Resource("pods").Name(POD_PREFIX + "-" + releaseSuffix + "-0").
Namespace(namespace).SubResource("exec")
req.VersionedParams(
option,
scheme.ParameterCodec,
)
exec, err := remotecommand.NewSPDYExecutor(cg.config, "POST", req.URL())
if err != nil {
return nil, nil, nil, err
}
err = exec.Stream(remotecommand.StreamOptions{
Stdin: &stdin,
Stdout: &stdout,
Stderr: &stderr,
})
if err != nil {
return nil, nil, nil, err
}
var config Config
err = yaml.Unmarshal(stdout.Bytes(), &config)
if err != nil {
return nil, nil, nil, err
}
caData, err := base64.StdEncoding.DecodeString(config.Clusters[0].Cluster.CertificateAuthorityData)
if err != nil {
return nil, nil, nil, err
}
cert, err := base64.StdEncoding.DecodeString(config.AuthInfos[0].AuthInfo.ClientCertificateData)
if err != nil {
return nil, nil, nil, err
}
key, err := base64.StdEncoding.DecodeString(config.AuthInfos[0].AuthInfo.ClientKeyData)
if err != nil {
return nil, nil, nil, err
}
return caData, cert, key, nil
}
//TODO: also should provision service for vcluster pod
func (cg *ClusterGenerator) installVCluster(opts *util.GenerateOpts, namespace string, releaseName string) error {
cmd, err := helm.NewCmd("/tmp", "v3", "")
if err != nil {
return err
}
log.Print("Execute helm install command")
_, err = cmd.Freestyle("install", releaseName, "vcluster", "--values", opts.ClusterOpts.ValuesFilePath, "--repo", "https://charts.loft.sh", "--namespace", namespace, "--repository-config", "", "--create-namespace", "--wait")
if err != nil {
return err
}
return nil
}
func (cg *ClusterGenerator) getClusterServerUri(namespace string, releaseSuffix string) (string, error) {
pod, err := cg.clientSet.CoreV1().Pods(namespace).Get(context.TODO(), POD_PREFIX+"-"+releaseSuffix+"-0", v12.GetOptions{})
if err != nil {
return "", err
}
// TODO: should be moved to service instead pod
return "https://" + pod.Status.PodIP + ":8443", nil
}
func (cg *ClusterGenerator) Generate(opts *util.GenerateOpts) error {
for i := 0; i < opts.ClusterOpts.Samples; i++ {
log.Printf("Generate cluster #%v", i)
namespace := opts.ClusterOpts.NamespacePrefix + "-" + util.GetRandomString()
log.Printf("Namespace is %s", namespace)
releaseSuffix := util.GetRandomString()
log.Printf("Release suffix is %s", namespace)
err := cg.installVCluster(opts, namespace, POD_PREFIX+"-"+releaseSuffix)
if err != nil {
log.Printf("Skip cluster installation due error %v", err.Error())
continue
}
log.Print("Get cluster credentials")
caData, cert, key, err := cg.getClusterCredentials(namespace, releaseSuffix)
if err != nil {
return err
}
log.Print("Get cluster server uri")
uri, err := cg.getClusterServerUri(namespace, releaseSuffix)
if err != nil {
return err
}
log.Printf("Cluster server uri is %s", uri)
log.Print("Create cluster")
_, err = cg.db.CreateCluster(context.TODO(), &argoappv1.Cluster{
Server: uri,
Name: opts.ClusterOpts.ClusterNamePrefix + "-" + util.GetRandomString(),
Config: argoappv1.ClusterConfig{
TLSClientConfig: argoappv1.TLSClientConfig{
Insecure: false,
ServerName: "kubernetes.default.svc",
CAData: caData,
CertData: cert,
KeyData: key,
},
},
ConnectionState: argoappv1.ConnectionState{},
ServerVersion: "1.18",
Namespaces: []string{opts.ClusterOpts.DestinationNamespace},
Labels: labels,
})
if err != nil {
return err
}
}
return nil
}
func (cg *ClusterGenerator) Clean(opts *util.GenerateOpts) error {
log.Printf("Clean clusters")
namespaces, err := cg.clientSet.CoreV1().Namespaces().List(context.TODO(), v12.ListOptions{})
if err != nil {
return err
}
for _, ns := range namespaces.Items {
if strings.HasPrefix(ns.Name, POD_PREFIX) {
log.Printf("Delete namespace %s", ns.Name)
err = cg.clientSet.CoreV1().Namespaces().Delete(context.TODO(), ns.Name, v12.DeleteOptions{})
if err != nil {
log.Printf("Delete namespace failed due: %s", err.Error())
}
}
}
secrets := cg.clientSet.CoreV1().Secrets(opts.Namespace)
return secrets.DeleteCollection(context.TODO(), v12.DeleteOptions{}, v12.ListOptions{
LabelSelector: "app.kubernetes.io/generated-by=argocd-generator",
})
}
+4 -8
View File
@@ -1,16 +1,12 @@
package generator
import "github.com/argoproj/argo-cd/v2/hack/gen-resources/util"
var labels = map[string]string{
"app.kubernetes.io/generated-by": "argocd-generator",
}
type GenerateOpts struct {
Samples int
GithubToken string
Namespace string
}
type Generator interface {
Generate(opts *GenerateOpts) error
Clean(opts *GenerateOpts) error
Generate(opts *util.GenerateOpts) error
Clean(opts *util.GenerateOpts) error
}
@@ -2,9 +2,11 @@ package generator
import (
"context"
"log"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/util"
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
)
@@ -17,9 +19,10 @@ func NewProjectGenerator(clientSet *appclientset.Clientset) Generator {
return &ProjectGenerator{clientSet}
}
func (pg *ProjectGenerator) Generate(opts *GenerateOpts) error {
func (pg *ProjectGenerator) Generate(opts *util.GenerateOpts) error {
projects := pg.clientSet.ArgoprojV1alpha1().AppProjects(opts.Namespace)
for i := 0; i < opts.Samples; i++ {
for i := 0; i < opts.ProjectOpts.Samples; i++ {
log.Printf("Generate project #%v", i)
_, err := projects.Create(context.TODO(), &v1alpha1.AppProject{
ObjectMeta: v1.ObjectMeta{
GenerateName: "project-",
@@ -31,13 +34,15 @@ func (pg *ProjectGenerator) Generate(opts *GenerateOpts) error {
},
}, v1.CreateOptions{})
if err != nil {
log.Printf("Project #%v failed to generate", i)
return err
}
}
return nil
}
func (pg *ProjectGenerator) Clean(opts *GenerateOpts) error {
func (pg *ProjectGenerator) Clean(opts *util.GenerateOpts) error {
log.Printf("Clean projects")
projects := pg.clientSet.ArgoprojV1alpha1().AppProjects(opts.Namespace)
return projects.DeleteCollection(context.TODO(), v1.DeleteOptions{}, v1.ListOptions{
LabelSelector: "app.kubernetes.io/generated-by=argocd-generator",
@@ -9,11 +9,11 @@ import (
"log"
"net/http"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/tools"
v1 "k8s.io/api/core/v1"
v1meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/v2/hack/gen-resources/util"
"k8s.io/client-go/kubernetes"
)
@@ -24,11 +24,11 @@ type Repo struct {
type RepoGenerator struct {
clientSet *kubernetes.Clientset
bar *tools.Bar
bar *util.Bar
}
func NewRepoGenerator(clientSet *kubernetes.Clientset) Generator {
return &RepoGenerator{clientSet: clientSet, bar: &tools.Bar{}}
return &RepoGenerator{clientSet: clientSet, bar: &util.Bar{}}
}
func fetchRepos(token string, page int) ([]Repo, error) {
@@ -79,8 +79,8 @@ func FetchRepos(token string, samples int) ([]Repo, error) {
return repos, nil
}
func (rg *RepoGenerator) Generate(opts *GenerateOpts) error {
repos, err := FetchRepos(opts.GithubToken, opts.Samples)
func (rg *RepoGenerator) Generate(opts *util.GenerateOpts) error {
repos, err := FetchRepos(opts.GithubToken, opts.RepositoryOpts.Samples)
if err != nil {
return err
}
@@ -116,7 +116,8 @@ func (rg *RepoGenerator) Generate(opts *GenerateOpts) error {
return nil
}
func (rg *RepoGenerator) Clean(opts *GenerateOpts) error {
func (rg *RepoGenerator) Clean(opts *util.GenerateOpts) error {
log.Printf("Clean repos")
secrets := rg.clientSet.CoreV1().Secrets(opts.Namespace)
return secrets.DeleteCollection(context.TODO(), v1meta.DeleteOptions{}, v1meta.ListOptions{
LabelSelector: "app.kubernetes.io/generated-by=argocd-generator",
@@ -0,0 +1,60 @@
package util
import (
"io/ioutil"
"gopkg.in/yaml.v2"
)
type SourceOpts struct {
Strategy string `yaml:"strategy"`
}
type DestinationOpts struct {
Strategy string `yaml:"strategy"`
}
type ApplicationOpts struct {
Samples int `yaml:"samples"`
SourceOpts SourceOpts `yaml:"source"`
DestinationOpts DestinationOpts `yaml:"destination"`
}
type RepositoryOpts struct {
Samples int `yaml:"samples"`
}
type ProjectOpts struct {
Samples int `yaml:"samples"`
}
type ClusterOpts struct {
Samples int `yaml:"samples"`
NamespacePrefix string `yaml:"namespacePrefix"`
ValuesFilePath string `yaml:"valuesFilePath"`
DestinationNamespace string `yaml:"destinationNamespace"`
ClusterNamePrefix string `yaml:"clusterNamePrefix"`
}
type GenerateOpts struct {
ApplicationOpts ApplicationOpts `yaml:"application"`
ClusterOpts ClusterOpts `yaml:"cluster"`
RepositoryOpts RepositoryOpts `yaml:"repository"`
ProjectOpts ProjectOpts `yaml:"project"`
GithubToken string
Namespace string `yaml:"namespace"`
}
func Parse(opts *GenerateOpts, file string) error {
fp, err := ioutil.ReadFile(file)
if err != nil {
return err
}
if e := yaml.Unmarshal(fp, &opts); e != nil {
return e
}
return nil
}
@@ -1,4 +1,4 @@
package tools
package util
import (
"log"
@@ -6,6 +6,8 @@ import (
"os/user"
"path"
"k8s.io/client-go/rest"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
@@ -36,11 +38,19 @@ func getKubeConfigPath() string {
func ConnectToK8sArgoClientSet() *appclientset.Clientset {
config, err := clientcmd.BuildConfigFromFlags("", getKubeConfigPath())
if err != nil {
log.Panicln("failed to create K8s config")
log.Panicln("failed to create Argocd K8s config")
}
return appclientset.NewForConfigOrDie(config)
}
func ConnectToK8sConfig() *rest.Config {
config, err := clientcmd.BuildConfigFromFlags("", getKubeConfigPath())
if err != nil {
log.Panicln("failed to create K8s config")
}
return config
}
func ConnectToK8sClientSet() *kubernetes.Clientset {
config, err := clientcmd.BuildConfigFromFlags("", getKubeConfigPath())
if err != nil {
@@ -1,4 +1,4 @@
package tools
package util
import (
"fmt"
+21
View File
@@ -0,0 +1,21 @@
package util
import (
"crypto/rand"
"math/big"
)
var letters = []rune("abcdefghijklmnopqrstuvwxyz123456789")
func GetRandomString() string {
b := make([]rune, 24)
for i := range b {
b[i] = letters[cryptoRandSecure(int64(len(letters)))]
}
return string(b)
}
func cryptoRandSecure(max int64) int64 {
nBig, _ := rand.Int(rand.Reader, big.NewInt(max))
return nBig.Int64()
}
+4
View File
@@ -338,6 +338,10 @@ func (c *Cmd) template(chartPath string, opts *TemplateOpts) (string, error) {
return c.run(args...)
}
func (c *Cmd) Freestyle(args ...string) (string, error) {
return c.run(args...)
}
func (c *Cmd) Close() {
_ = os.RemoveAll(c.helmHome)
}