mirror of
https://github.com/hanzoai/deploy.git
synced 2026-10-07 08:44:50 +00:00
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:
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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",
|
||||
})
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user