diff --git a/capten/common-pkg/plugins/argocd/applications.go b/capten/common-pkg/plugins/argocd/applications.go new file mode 100644 index 00000000..bf0f45a2 --- /dev/null +++ b/capten/common-pkg/plugins/argocd/applications.go @@ -0,0 +1,142 @@ +package argocd + +import ( + "context" + "encoding/json" + + "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" + "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/argoproj/argo-cd/v2/util/io" + "github.com/kube-tarian/kad/capten/model" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func (a *ArgoCDClient) Create(req *model.CreteRequestPayload) (json.RawMessage, error) { + conn, appClient, err := a.client.NewApplicationClient() + if err != nil { + a.logger.Errorf("Application client intilialization failed: %v", err) + return nil, err + } + defer io.Close(conn) + resp, err := appClient.Create( + context.Background(), + &application.ApplicationCreateRequest{ + Application: &v1alpha1.Application{ + ObjectMeta: v1.ObjectMeta{ + Name: req.ReleaseName, + }, + Spec: v1alpha1.ApplicationSpec{ + Destination: v1alpha1.ApplicationDestination{ + Namespace: req.Namespace, + Server: "https://kubernetes.default.svc", + }, + Source: v1alpha1.ApplicationSource{ + RepoURL: req.RepoURL, + Path: req.ChartName, + TargetRevision: "HEAD", + }, + SyncPolicy: &v1alpha1.SyncPolicy{ + Automated: &v1alpha1.SyncPolicyAutomated{ + Prune: false, + SelfHeal: false, + }, + }, + Project: "default", + }, + }, + }) + if err != nil { + a.logger.Errorf("Application %s install failed: %v", req.ReleaseName, err) + return nil, err + } + + respMsg, err := json.Marshal(resp) + if err != nil { + return nil, err + } + // a.logger.Infof("argo-cd msg: %s", string(respMsg)) + return respMsg, nil +} + +func (a *ArgoCDClient) Delete(req *model.DeleteRequestPayload) (json.RawMessage, error) { + conn, appClient, err := a.client.NewApplicationClient() + if err != nil { + return nil, err + } + defer io.Close(conn) + + resp, err := appClient.Delete( + context.Background(), + &application.ApplicationDeleteRequest{ + Name: &req.ReleaseName, + AppNamespace: &req.Namespace, + }, + ) + if err != nil { + return nil, err + } + + respMsg, err := json.Marshal(resp) + if err != nil { + return nil, err + } + return respMsg, nil +} + +func (a *ArgoCDClient) List(req *model.ListRequestPayload) (json.RawMessage, error) { + conn, appClient, err := a.client.NewApplicationClient() + if err != nil { + return nil, err + } + defer io.Close(conn) + + list, err := appClient.List(context.Background(), &application.ApplicationQuery{}) + if err != nil { + return nil, err + } + + listMsg, err := json.Marshal(list) + if err != nil { + return nil, err + } + return listMsg, nil +} + +func (a *ArgoCDClient) TriggerAppSync(ctx context.Context, namespace, name string) (*v1alpha1.Application, error) { + conn, app, err := a.client.NewApplicationClient() + if err != nil { + return nil, err + } + + defer conn.Close() + + pruneApp := true + resp, err := app.Sync(ctx, &application.ApplicationSyncRequest{ + Name: &name, + AppNamespace: &namespace, + Prune: &pruneApp, + RetryStrategy: &v1alpha1.RetryStrategy{ + Limit: 3, + }}) + if err != nil { + return nil, err + } + + return resp, err +} + +func (a *ArgoCDClient) GetAppSyncStatus(ctx context.Context, namespace, name string) (*v1alpha1.Application, error) { + conn, app, err := a.client.NewApplicationClient() + if err != nil { + return nil, err + } + + defer conn.Close() + + resp, err := app.Get(ctx, &application.ApplicationQuery{Name: &name, AppNamespace: &namespace}) + if err != nil { + return nil, err + } + + return resp, err +} diff --git a/capten/common-pkg/plugins/argocd/client.go b/capten/common-pkg/plugins/argocd/client.go index f03f4e9d..0420830d 100644 --- a/capten/common-pkg/plugins/argocd/client.go +++ b/capten/common-pkg/plugins/argocd/client.go @@ -1,22 +1,12 @@ package argocd import ( - "context" - "encoding/json" "fmt" - "net/url" "github.com/argoproj/argo-cd/v2/pkg/apiclient" - "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" - "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" - "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - "github.com/argoproj/argo-cd/v2/util/io" "github.com/intelops/go-common/logging" "github.com/kelseyhightower/envconfig" "github.com/kube-tarian/kad/capten/common-pkg/k8s" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/fetcher" - "github.com/kube-tarian/kad/capten/model" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type ArgoCDClient struct { @@ -64,284 +54,3 @@ func NewClient(logger logging.Logger) (*ArgoCDClient, error) { client: client, }, nil } - -func (a *ArgoCDClient) ConfigurationActivities(req interface{}) (json.RawMessage, error) { - payload, _ := req.(model.ConfigPayload) - switch payload.Resource { - case "cluster": - return a.HandleCluster(req) - case "repo": - return a.HandleRepo(payload) - default: - return nil, fmt.Errorf("unsupported action for argocd plugin: %v", payload.Action) - } -} - -func (a *ArgoCDClient) HandleCluster(req interface{}) (json.RawMessage, error) { - payload, _ := req.(model.ConfigPayload) - switch payload.Action { - case "add": - // return a.ClusterAdd(payload) - case "delete": - // return a.ClusterDelete(payload) - case "list": - // return a.ClusterList(payload) - default: - return nil, fmt.Errorf("unsupported action for argocd plugin: %v", payload.Action) - } - return nil, nil -} - -func (a *ArgoCDClient) HandleRepo(req interface{}) (json.RawMessage, error) { - payload, _ := req.(model.ConfigPayload) - switch payload.Action { - case "add": - // return a.RepoAdd(payload) - case "delete": - // return a.RepoDelete(payload) - case "list": - // return a.RepoList(payload) - default: - return nil, fmt.Errorf("unsupported action for argocd plugin: %v", payload.Action) - } - return nil, nil -} - -func fetchConfiguration(log logging.Logger) (*Configuration, error) { - // If ARGOCD_PASSWORD env variable is configured then it will use local default configuration - // Else it uses fetched to get the plugin details and prepares the configuration - cfg := &Configuration{} - err := envconfig.Process("", cfg) - if err == nil { - return cfg, err - } - - fetcherClient, err := fetcher.NewCredentialFetcher(log) - if err != nil { - log.Errorf("fetcher client initialization failed: %v", err) - return nil, err - } - - response, err := fetcherClient.FetchPluginDetails(&fetcher.PluginRequest{ - PluginName: "argocd", - }) - if err != nil { - log.Errorf("Failed to get the plugin details: %v", err) - return nil, err - } - cfg = &Configuration{ - ServiceURL: response.ServiceURL, - IsSSLEnabled: response.IsSSLEnabled, - Username: response.Username, - Password: response.Password, - } - return cfg, err -} - -func (a *ArgoCDClient) Create(req *model.CreteRequestPayload) (json.RawMessage, error) { - conn, appClient, err := a.client.NewApplicationClient() - if err != nil { - a.logger.Errorf("Application client intilialization failed: %v", err) - return nil, err - } - defer io.Close(conn) - resp, err := appClient.Create( - context.Background(), - &application.ApplicationCreateRequest{ - Application: &v1alpha1.Application{ - ObjectMeta: v1.ObjectMeta{ - Name: req.ReleaseName, - }, - Spec: v1alpha1.ApplicationSpec{ - Destination: v1alpha1.ApplicationDestination{ - Namespace: req.Namespace, - Server: "https://kubernetes.default.svc", - }, - Source: v1alpha1.ApplicationSource{ - RepoURL: req.RepoURL, - Path: req.ChartName, - TargetRevision: "HEAD", - }, - SyncPolicy: &v1alpha1.SyncPolicy{ - Automated: &v1alpha1.SyncPolicyAutomated{ - Prune: false, - SelfHeal: false, - }, - }, - Project: "default", - }, - }, - }) - if err != nil { - a.logger.Errorf("Application %s install failed: %v", req.ReleaseName, err) - return nil, err - } - - respMsg, err := json.Marshal(resp) - if err != nil { - return nil, err - } - // a.logger.Infof("argo-cd msg: %s", string(respMsg)) - return respMsg, nil -} - -func (a *ArgoCDClient) Delete(req *model.DeleteRequestPayload) (json.RawMessage, error) { - conn, appClient, err := a.client.NewApplicationClient() - if err != nil { - return nil, err - } - defer io.Close(conn) - - resp, err := appClient.Delete( - context.Background(), - &application.ApplicationDeleteRequest{ - Name: &req.ReleaseName, - AppNamespace: &req.Namespace, - }, - ) - if err != nil { - return nil, err - } - - respMsg, err := json.Marshal(resp) - if err != nil { - return nil, err - } - return respMsg, nil -} - -func (a *ArgoCDClient) List(req *model.ListRequestPayload) (json.RawMessage, error) { - conn, appClient, err := a.client.NewApplicationClient() - if err != nil { - return nil, err - } - defer io.Close(conn) - - list, err := appClient.List(context.Background(), &application.ApplicationQuery{}) - if err != nil { - return nil, err - } - - listMsg, err := json.Marshal(list) - if err != nil { - return nil, err - } - return listMsg, nil -} - -func (a *ArgoCDClient) ListRepositories(ctx context.Context) (*v1alpha1.RepositoryList, error) { - conn, appClient, err := a.client.NewRepoClient() - if err != nil { - return nil, err - } - defer io.Close(conn) - - list, err := appClient.ListRepositories(ctx, &repository.RepoQuery{}) - if err != nil { - return nil, err - } - - return list, nil -} - -func (a *ArgoCDClient) CreateRepository(ctx context.Context, repo *Repository) (*v1alpha1.Repository, error) { - conn, appClient, err := a.client.NewRepoClient() - if err != nil { - return nil, err - } - defer io.Close(conn) - - resp, err := appClient.CreateRepository(ctx, &repository.RepoCreateRequest{ - Repo: &v1alpha1.Repository{ - Project: repo.Project, - Repo: repo.Repo, - Username: repo.Username, - Password: repo.Password, - Type: repo.Type, - Insecure: repo.Insecure, - EnableLFS: repo.EnableLFS, - InsecureIgnoreHostKey: repo.InsecureIgnoreHostKey, - ConnectionState: v1alpha1.ConnectionState{ - Status: repo.ConnectionState.Status, - Message: repo.ConnectionState.Message, - }, - }, - }) - if err != nil { - return nil, err - } - return resp, nil -} - -func (a *ArgoCDClient) DeleteRepository(ctx context.Context, repo string) (*repository.RepoResponse, error) { - conn, appClient, err := a.client.NewRepoClient() - if err != nil { - return nil, err - } - defer io.Close(conn) - - encodedRepo := url.QueryEscape(repo) - - resp, err := appClient.DeleteRepository(ctx, &repository.RepoQuery{Repo: encodedRepo}) - if err != nil { - return nil, err - } - - return resp, nil -} - -func (a *ArgoCDClient) GetRepository(ctx context.Context, repo string) (*v1alpha1.Repository, error) { - conn, appClient, err := a.client.NewRepoClient() - if err != nil { - return nil, err - } - defer io.Close(conn) - - encodedRepo := url.QueryEscape(repo) - - repository, err := appClient.Get(ctx, &repository.RepoQuery{Repo: encodedRepo}) - if err != nil { - return nil, err - } - - return repository, nil -} - -func (a *ArgoCDClient) TriggerAppSync(ctx context.Context, namespace, name string) (*v1alpha1.Application, error) { - conn, app, err := a.client.NewApplicationClient() - if err != nil { - return nil, err - } - - defer conn.Close() - - pruneApp := true - resp, err := app.Sync(ctx, &application.ApplicationSyncRequest{ - Name: &name, - AppNamespace: &namespace, - Prune: &pruneApp, - RetryStrategy: &v1alpha1.RetryStrategy{ - Limit: 3, - }}) - if err != nil { - return nil, err - } - - return resp, err -} - -func (a *ArgoCDClient) GetAppSyncStatus(ctx context.Context, namespace, name string) (*v1alpha1.Application, error) { - conn, app, err := a.client.NewApplicationClient() - if err != nil { - return nil, err - } - - defer conn.Close() - - resp, err := app.Get(ctx, &application.ApplicationQuery{Name: &name, AppNamespace: &namespace}) - if err != nil { - return nil, err - } - - return resp, err -} diff --git a/capten/common-pkg/plugins/argocd/clusters.go b/capten/common-pkg/plugins/argocd/clusters.go new file mode 100644 index 00000000..575a3151 --- /dev/null +++ b/capten/common-pkg/plugins/argocd/clusters.go @@ -0,0 +1,2 @@ +package argocd + diff --git a/capten/common-pkg/plugins/argocd/repositories.go b/capten/common-pkg/plugins/argocd/repositories.go new file mode 100644 index 00000000..52b70722 --- /dev/null +++ b/capten/common-pkg/plugins/argocd/repositories.go @@ -0,0 +1,88 @@ +package argocd + +import ( + "context" + "net/url" + + "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" + "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/argoproj/argo-cd/v2/util/io" +) + +func (a *ArgoCDClient) CreateRepository(ctx context.Context, repo *Repository) (*v1alpha1.Repository, error) { + conn, appClient, err := a.client.NewRepoClient() + if err != nil { + return nil, err + } + defer io.Close(conn) + + resp, err := appClient.CreateRepository(ctx, &repository.RepoCreateRequest{ + Repo: &v1alpha1.Repository{ + Project: repo.Project, + Repo: repo.Repo, + Username: repo.Username, + Password: repo.Password, + Type: repo.Type, + Insecure: repo.Insecure, + EnableLFS: repo.EnableLFS, + InsecureIgnoreHostKey: repo.InsecureIgnoreHostKey, + ConnectionState: v1alpha1.ConnectionState{ + Status: repo.ConnectionState.Status, + Message: repo.ConnectionState.Message, + }, + }, + }) + if err != nil { + return nil, err + } + return resp, nil +} + +func (a *ArgoCDClient) DeleteRepository(ctx context.Context, repo string) (*repository.RepoResponse, error) { + conn, appClient, err := a.client.NewRepoClient() + if err != nil { + return nil, err + } + defer io.Close(conn) + + encodedRepo := url.QueryEscape(repo) + + resp, err := appClient.DeleteRepository(ctx, &repository.RepoQuery{Repo: encodedRepo}) + if err != nil { + return nil, err + } + + return resp, nil +} + +func (a *ArgoCDClient) GetRepository(ctx context.Context, repo string) (*v1alpha1.Repository, error) { + conn, appClient, err := a.client.NewRepoClient() + if err != nil { + return nil, err + } + defer io.Close(conn) + + encodedRepo := url.QueryEscape(repo) + + repository, err := appClient.Get(ctx, &repository.RepoQuery{Repo: encodedRepo}) + if err != nil { + return nil, err + } + + return repository, nil +} + +func (a *ArgoCDClient) ListRepositories(ctx context.Context) (*v1alpha1.RepositoryList, error) { + conn, appClient, err := a.client.NewRepoClient() + if err != nil { + return nil, err + } + defer io.Close(conn) + + list, err := appClient.ListRepositories(ctx, &repository.RepoQuery{}) + if err != nil { + return nil, err + } + + return list, nil +} diff --git a/capten/common-pkg/plugins/fetcher/cluster_store.go b/capten/common-pkg/plugins/fetcher/cluster_store.go deleted file mode 100644 index 56c51daa..00000000 --- a/capten/common-pkg/plugins/fetcher/cluster_store.go +++ /dev/null @@ -1,46 +0,0 @@ -package fetcher - -import ( - "github.com/kelseyhightower/envconfig" - "github.com/intelops/go-common/logging" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/utils" -) - -const ( - FetchClusterQuery = `select name, kubeconfig from clusters where name = ?;` -) - -type ClusterStoreConfiguration struct { - TableName string `envconfig:"CASSANDRA_CLUSTER_TABLE_NAME" default:"clusters"` -} - -func FetchClusterDetails(log logging.Logger, clusterName string) (*ClusterDetails, error) { - cfg := &ClusterStoreConfiguration{} - err := envconfig.Process("", cfg) - if err != nil { - log.Errorf("Cassandra configuration detail missing, %v", err) - return nil, err - } - - // Fetch the plugin details from Cassandra - store, err := utils.NewStore(log) - if err != nil { - log.Errorf("Store initialization failed, %v", err) - return nil, err - } - defer store.Close() - - pd := &ClusterDetails{} - // name, kubeconfig - query := store.GetSession().Query(FetchClusterQuery, clusterName) - err = query.Scan( - &pd.Name, - &pd.Kubeconfig, - ) - - if err != nil { - log.Errorf("Fetch plugin details failed, %v", err) - return nil, err - } - return pd, nil -} diff --git a/capten/common-pkg/plugins/fetcher/credential.go b/capten/common-pkg/plugins/fetcher/credential.go deleted file mode 100644 index 09d8d640..00000000 --- a/capten/common-pkg/plugins/fetcher/credential.go +++ /dev/null @@ -1,71 +0,0 @@ -package fetcher - -// This package is to fetch the credentials for plugins used in capten -// Fetches the plugin details from Cassandra -// It uses kubernetes clientset to fetch plugin credential details from underlying kubernetes using details fetched from cassandra - -import ( - "fmt" - - "github.com/intelops/go-common/logging" - "github.com/kube-tarian/kad/capten/common-pkg/k8s" -) - -type CredentialFetcher struct { - k8sClient *k8s.K8SClient - log logging.Logger -} - -func NewCredentialFetcher(log logging.Logger) (*CredentialFetcher, error) { - k8sClient, err := k8s.NewK8SClient(log) - if err != nil { - log.Errorf("K8S client initialization failed: %v", err) - return nil, fmt.Errorf("k8 client initialization failed, %v", err) - } - - return &CredentialFetcher{ - k8sClient: k8sClient, - log: log, - }, nil -} - -func (c *CredentialFetcher) FetchPluginDetails(req *PluginRequest) (*PluginResponse, error) { - // Fetch the plugin details from Cassandra - pluginDetails, err := FetchPluginDetails(c.log, req.PluginName) - if err != nil { - c.log.Errorf("Failed to fetch plugin details from store, %v", err) - return nil, err - } - - // Fetch the plugin credentials from Kubernetes - switch req.PluginName { - case "argocd": - return c.FetchArgoCDDetails( - pluginDetails.Namespace, - pluginDetails.ReleaseName+"-server", - ) - } - - return nil, fmt.Errorf("unsupported plugin: %s", req.PluginName) -} - -func (c *CredentialFetcher) FetchArgoCDDetails(namespace, releaseName string) (*PluginResponse, error) { - service, err := c.k8sClient.GetServiceData(namespace, releaseName) - if err != nil { - return nil, fmt.Errorf("fetching plugin credentials failed: %v", err) - } - // Depending on the service port details isSSLEnabled can be prepared. For now it is set to false default scenario - isSSLEnabled := false - - credentialDetails, err := c.k8sClient.GetSecretData(namespace, "argocd-initial-admin-secret") - if err != nil { - c.log.Errorf("Fetching plugin credentials failed: %v", err) - return nil, err - } - return &PluginResponse{ - ServiceURL: fmt.Sprintf("%s.%s.svc.cluster.local", service.Name, namespace), - IsSSLEnabled: isSSLEnabled, - Username: "admin", // admin user is not available in secret - Password: credentialDetails.Data["password"], - }, nil -} diff --git a/capten/common-pkg/plugins/fetcher/model.go b/capten/common-pkg/plugins/fetcher/model.go deleted file mode 100644 index 263433a0..00000000 --- a/capten/common-pkg/plugins/fetcher/model.go +++ /dev/null @@ -1,27 +0,0 @@ -package fetcher - -type PluginRequest struct { - PluginName string -} - -type PluginResponse struct { - ServiceURL string - IsSSLEnabled bool - Username string - Password string -} - -type PluginDetails struct { - Name string - RepoName string - RepoURL string - ChartName string - Namespace string - ReleaseName string - Version string -} - -type ClusterDetails struct { - Name string - Kubeconfig string -} diff --git a/capten/common-pkg/plugins/fetcher/plugin_store.go b/capten/common-pkg/plugins/fetcher/plugin_store.go deleted file mode 100644 index a511b431..00000000 --- a/capten/common-pkg/plugins/fetcher/plugin_store.go +++ /dev/null @@ -1,50 +0,0 @@ -package fetcher - -import ( - "github.com/kelseyhightower/envconfig" - "github.com/intelops/go-common/logging" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/utils" -) - -const ( - FetchPluginQuery = `select name, repo_name, repo_url, chart_name, namespace, release_name, version from tools where name = ?;` -) - -type PluginConfiguration struct { - TableName string `envconfig:"CASSANDRA_TABLE_NAME" default:"tools"` -} - -func FetchPluginDetails(log logging.Logger, pluginName string) (*PluginDetails, error) { - cfg := &PluginConfiguration{} - err := envconfig.Process("", cfg) - if err != nil { - log.Errorf("Cassandra configuration detail missing, %v", err) - return nil, err - } - - // Fetch the plugin details from Cassandra - store, err := utils.NewStore(log) - if err != nil { - log.Errorf("Store initialization failed, %v", err) - return nil, err - } - defer store.Close() - - pd := &PluginDetails{} - // name, repo_name, repo_url, chart_name, namespace, release_name, version - err = store.GetSession().Query(FetchPluginQuery, pluginName).Scan( - &pd.Name, - &pd.RepoName, - &pd.RepoURL, - &pd.ChartName, - &pd.Namespace, - &pd.ReleaseName, - &pd.Version, - ) - - if err != nil { - log.Errorf("Fetch plugin details failed, %v", err) - return nil, err - } - return pd, nil -} diff --git a/capten/common-pkg/plugins/git/git.go b/capten/common-pkg/plugins/git/git.go index 308201d3..977e5db6 100644 --- a/capten/common-pkg/plugins/git/git.go +++ b/capten/common-pkg/plugins/git/git.go @@ -12,15 +12,15 @@ import ( "github.com/go-git/go-git/v5/plumbing/transport/http" ) -type Operation struct { +type GitClient struct { repository *git.Repository } -func New() *Operation { - return &Operation{} +func NewClient() *GitClient { + return &GitClient{} } -func (op *Operation) Clone(directory, url, token string) error { +func (g *GitClient) Clone(directory, url, token string) error { r, err := git.PlainClone(directory, false, &git.CloneOptions{ Auth: &http.BasicAuth{ Username: "dummy", // yes, this can be anything except an empty string @@ -35,13 +35,12 @@ func (op *Operation) Clone(directory, url, token string) error { return err } - op.repository = r - + g.repository = r return nil } -func (op *Operation) Commit(path, msg, name, email string) error { - w, err := op.repository.Worktree() +func (g *GitClient) Commit(path, msg, name, email string) error { + w, err := g.repository.Worktree() if err != nil { return err } @@ -66,8 +65,8 @@ func (op *Operation) Commit(path, msg, name, email string) error { return nil } -func (op *Operation) GetDefaultBranchName() (string, error) { - defBranch, err := op.repository.Head() +func (g *GitClient) GetDefaultBranchName() (string, error) { + defBranch, err := g.repository.Head() if err != nil { return "", fmt.Errorf("failed to get the current head: %w", err) } @@ -76,13 +75,13 @@ func (op *Operation) GetDefaultBranchName() (string, error) { return defaultBranch[len(defaultBranch)-1], nil } -func (op *Operation) Push(branchName, token string) error { - defBranch, err := op.GetDefaultBranchName() +func (g *GitClient) Push(branchName, token string) error { + defBranch, err := g.GetDefaultBranchName() if err != nil { return fmt.Errorf("failed to get the current head: %w", err) } - err = op.repository.Push(&git.PushOptions{RemoteName: "origin", Force: true, + err = g.repository.Push(&git.PushOptions{RemoteName: "origin", Force: true, Auth: &http.BasicAuth{ Username: "dummy", // yes, this can be anything except an empty string Password: token, diff --git a/capten/common-pkg/plugins/github/github.go b/capten/common-pkg/plugins/github/github.go deleted file mode 100644 index f6bf3f22..00000000 --- a/capten/common-pkg/plugins/github/github.go +++ /dev/null @@ -1,48 +0,0 @@ -package github - -import ( - "context" - "crypto/tls" - "net/http" - - "github.com/google/go-github/v55/github" -) - -type Operations interface { - CreatePR(ctx context.Context, prRepo, prRepoOwner, prSubject, commitBranch, - repoBranch, prBranch, prDescription string) (string, error) -} - -type Operation struct { - client *github.Client -} - -func NewOperation(token string) *Operation { - httpClient := &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - } - - client := github.NewClient(httpClient).WithAuthToken(token) - return &Operation{client: client} -} - -func (op *Operation) CreatePR(ctx context.Context, prRepo, prRepoOwner, prSubject, - commitBranch, repoBranch, prDescription string) (string, error) { - newPR := &github.NewPullRequest{ - Title: &prSubject, - Head: &commitBranch, - HeadRepo: &repoBranch, - Base: &repoBranch, - Body: &prDescription, - MaintainerCanModify: github.Bool(true), - } - - pr, _, err := op.client.PullRequests.Create(ctx, prRepoOwner, prRepo, newPR) - if err != nil { - return "", err - } - - return pr.GetHTMLURL(), nil -} diff --git a/capten/common-pkg/plugins/helm/create.go b/capten/common-pkg/plugins/helm/create.go index 7ba161ce..9185aefb 100644 --- a/capten/common-pkg/plugins/helm/create.go +++ b/capten/common-pkg/plugins/helm/create.go @@ -6,11 +6,8 @@ import ( "fmt" "time" - jsoniter "github.com/json-iterator/go" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/fetcher" helmclient "github.com/kube-tarian/kad/capten/common-pkg/plugins/helm/go-helm-client" "github.com/kube-tarian/kad/capten/model" - "gopkg.in/yaml.v2" "helm.sh/helm/v3/pkg/repo" ) @@ -71,50 +68,7 @@ func (h *HelmCLient) getHelmClient(namespace string) (helmclient.Client, error) DebugLog: h.logger.Debugf, } - // If kubeconfig is empty (default) or inbuilt then use in-built(local) cluster - // if req.ClusterName == "" || req.ClusterName == "inbuilt" { return helmclient.New(opt) - // } - - // External cluster - // return h.getHelmClientForExternalCluster(req, opt) -} - -func (h *HelmCLient) getHelmClientForExternalCluster(req *model.Request, opt *helmclient.Options) (helmclient.Client, error) { - // Fetch external cluster kubeconfig from cassandra - clusterDetails, err := fetcher.FetchClusterDetails(h.logger, req.ClusterName) - if err != nil { - h.logger.Errorf("Failed to fetch the cluster details from cluster store, %v", err) - } - - // Unmarshall kubeconfig in yaml format if failed try with json format - // If not both yaml and json return error - var yamlKubeConfig interface{} - var jsonKubeConfig []byte - - err = yaml.Unmarshal([]byte(clusterDetails.Kubeconfig), &yamlKubeConfig) - if err == nil { - jsonKubeConfig, err = jsoniter.Marshal(yamlKubeConfig) - if err != nil { - h.logger.Errorf("json Marhsal of kubeconfig failed, err: json Mashal: %v", err) - return nil, err - } - } else { - err1 := json.Unmarshal([]byte(clusterDetails.Kubeconfig), yamlKubeConfig) - if err1 != nil { - h.logger.Errorf("kubeconfig not understanable format not in yaml or json. unmarshal failed, error: %v", err) - return nil, err - } - jsonKubeConfig = []byte(clusterDetails.Kubeconfig) - } - - return helmclient.NewClientFromKubeConf( - &helmclient.KubeConfClientOptions{ - Options: opt, - KubeContext: req.ClusterName, - KubeConfig: jsonKubeConfig, - }, - ) } func (h *HelmCLient) addOrUpdate(client helmclient.Client, req *model.CreteRequestPayload) error { diff --git a/capten/common-pkg/plugins/plugins.go b/capten/common-pkg/plugins/plugins.go deleted file mode 100644 index b91b161a..00000000 --- a/capten/common-pkg/plugins/plugins.go +++ /dev/null @@ -1,22 +0,0 @@ -package plugins - -import ( - "fmt" - "strings" - - "github.com/intelops/go-common/logging" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/argocd" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/helm" - workerframework "github.com/kube-tarian/kad/capten/common-pkg/worker-framework" -) - -func GetPlugin(plugin string, logger logging.Logger) (workerframework.Plugin, error) { - switch strings.ToLower(plugin) { - case "helm": - return helm.NewClient(logger) - case "argocd": - return argocd.NewClient(logger) - default: - return nil, fmt.Errorf("plugin %s not found", plugin) - } -} diff --git a/capten/common-pkg/plugins/utils/cassandra_store.go b/capten/common-pkg/plugins/utils/cassandra_store.go deleted file mode 100644 index 634862d6..00000000 --- a/capten/common-pkg/plugins/utils/cassandra_store.go +++ /dev/null @@ -1,63 +0,0 @@ -package utils - -import ( - "github.com/gocql/gocql" - "github.com/kelseyhightower/envconfig" - "github.com/intelops/go-common/logging" -) - -type Configuration struct { - ServiceURL []string `envconfig:"CASSANDRA_SERVICE_URL" required:"true"` - Username string `envconfig:"CASSANDRA_USERNAME" required:"true"` - Password string `envconfig:"CASSANDRA_PASSWORD" required:"true"` - KeyspaceName string `envconfig:"CASSANDRA_KEYSPACE_NAME" required:"true"` - TableName string `envconfig:"CASSANDRA_TABLE_NAME" required:"true"` -} - -type Store struct { - log logging.Logger - - conf *Configuration - session *gocql.Session -} - -func NewStore(log logging.Logger) (*Store, error) { - cfg := &Configuration{} - err := envconfig.Process("", cfg) - if err != nil { - log.Errorf("Cassandra configuration detail missing, %v", err) - return nil, err - } - - // Create gocql client - cluster := gocql.NewCluster(cfg.ServiceURL...) - cluster.Keyspace = cfg.KeyspaceName - cluster.Consistency = gocql.Quorum - cluster.Authenticator = gocql.PasswordAuthenticator{ - Username: cfg.Username, - Password: cfg.Password, - } - // cluster.SslOpts = &gocql.SslOptions{ - // EnableHostVerification: false, - // } - - session, err := cluster.CreateSession() - if err != nil { - log.Errorf("Cassandra session creation failed, %v", err) - return nil, err - } - - return &Store{ - log: log, - conf: cfg, - session: session, - }, nil -} - -func (s *Store) GetSession() *gocql.Session { - return s.session -} - -func (s *Store) Close() { - s.session.Close() -} diff --git a/capten/common-pkg/plugins/utils/cassandra_store_test.go b/capten/common-pkg/plugins/utils/cassandra_store_test.go deleted file mode 100644 index 80444ee7..00000000 --- a/capten/common-pkg/plugins/utils/cassandra_store_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package utils - -import ( - "os" - "testing" - - "github.com/intelops/go-common/logging" - "github.com/stretchr/testify/assert" -) - -var log = logging.NewLogger() - -func TestFetchArgoCDPluginDetails(t *testing.T) { - os.Setenv("CASSANDRA_SERVICE_URL", "127.0.0.1:9042") - os.Setenv("CASSANDRA_USERNAME", "user") - os.Setenv("CASSANDRA_PASSWORD", "password") - os.Setenv("CASSANDRA_KEYSPACE_NAME", "capten") - os.Setenv("CASSANDRA_TABLE_NAME", "tools") - - store, err := NewStore(log) - assert.Nilf(t, err, "Store initialization should be passed") - if err != nil { - return - } - assert.NotNilf(t, store, "store session should get initialized") - - // pd, err := store.FetchPluginDetails("argocd") - // assert.Nilf(t, err, "argocd plugin details should be able fetch") - // assert.NotNilf(t, pd, "argocd plugin details failed to fetch") - // if err != nil { - // return - // } - - // t.Logf("argocd plugin details: %+v", pd) -} diff --git a/capten/common-pkg/worker-framework/event_processor.go b/capten/common-pkg/worker-framework/event_processor.go index cc64f327..71f579ad 100644 --- a/capten/common-pkg/worker-framework/event_processor.go +++ b/capten/common-pkg/worker-framework/event_processor.go @@ -1,48 +1,15 @@ package workerframework import ( - "encoding/json" "fmt" "github.com/intelops/go-common/logging" "github.com/kelseyhightower/envconfig" "github.com/kube-tarian/kad/capten/common-pkg/temporalclient" - "github.com/kube-tarian/kad/capten/model" "go.temporal.io/sdk/worker" ) -type Plugin interface { - // DeployActivities(payload interface{}) (json.RawMessage, error) - Create(payload *model.CreteRequestPayload) (json.RawMessage, error) - Delete(payload *model.DeleteRequestPayload) (json.RawMessage, error) - List(payload *model.ListRequestPayload) (json.RawMessage, error) - - // ConfigurationActivities(payload interface{}) (json.RawMessage, error) - // ConfgiureTarget(payload interface{}) (json.RawMessage, error) - // SetTarget(payload interface{}) (json.RawMessage, error) - // SetDefaultTarget(payload interface{}) (json.RawMessage, error) -} - -type ClimonWorker interface { - Create(payload *model.CreteRequestPayload) (json.RawMessage, error) - Delete(payload *model.DeleteRequestPayload) (json.RawMessage, error) - List(payload *model.ListRequestPayload) (json.RawMessage, error) -} - -type DeploymentWorker interface { - Create(payload *model.CreteRequestPayload) (json.RawMessage, error) - Delete(payload *model.DeleteRequestPayload) (json.RawMessage, error) - List(payload *model.ListRequestPayload) (json.RawMessage, error) -} - -type ConfigureCICD interface { - Clone(directory, url, token string) error - Commit(path, msg, name, email string) error - Push(branchName, token string) error - GetDefaultBranchName() (string, error) -} - type Action interface { GetStatus() } @@ -55,7 +22,6 @@ type Worker struct { conf *Configuration temporalClient *temporalclient.Client temporalWorker worker.Worker - plugins map[string]Plugin logger logging.Logger } @@ -66,9 +32,8 @@ func NewWorker(taskQueueName string, wf, activity interface{}, logger logging.Lo } worker := &Worker{ - conf: cfg, - plugins: make(map[string]Plugin), - logger: logger, + conf: cfg, + logger: logger, } err = worker.RegisterToTemporal(taskQueueName, wf, activity) diff --git a/capten/config-worker/internal/app_config/app_git_helper.go b/capten/config-worker/internal/app_config/app_git_helper.go index 72ad3472..378976a6 100644 --- a/capten/config-worker/internal/app_config/app_git_helper.go +++ b/capten/config-worker/internal/app_config/app_git_helper.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "os" - "strings" "time" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" @@ -13,8 +12,6 @@ import ( "github.com/kelseyhightower/envconfig" "github.com/kube-tarian/kad/capten/common-pkg/k8s" "github.com/kube-tarian/kad/capten/common-pkg/plugins/git" - "github.com/kube-tarian/kad/capten/common-pkg/plugins/github" - workerframework "github.com/kube-tarian/kad/capten/common-pkg/worker-framework" "github.com/pkg/errors" "github.com/kube-tarian/kad/capten/common-pkg/plugins/argocd" @@ -38,7 +35,7 @@ var logger = logging.NewLogger() type AppGitConfigHelper struct { cfg Config - gitPlugin workerframework.ConfigureCICD + gitClient *git.GitClient } func NewAppGitConfigHelper() (*AppGitConfigHelper, error) { @@ -46,7 +43,7 @@ func NewAppGitConfigHelper() (*AppGitConfigHelper, error) { if err := envconfig.Process("", &cfg); err != nil { return nil, err } - return &AppGitConfigHelper{cfg: cfg, gitPlugin: git.New()}, nil + return &AppGitConfigHelper{cfg: cfg, gitClient: git.NewClient()}, nil } func (ca *AppGitConfigHelper) GetAccessToken(ctx context.Context, projectId string) (string, error) { @@ -75,7 +72,7 @@ func (ca *AppGitConfigHelper) CloneRepos(ctx context.Context, templateRepo, cust return } - if err = ca.gitPlugin.Clone(templateDir, templateRepo, token); err != nil { + if err = ca.gitClient.Clone(templateDir, templateRepo, token); err != nil { os.RemoveAll(templateDir) err = fmt.Errorf("failed to Clone template repo, err: %v", err) return @@ -88,7 +85,7 @@ func (ca *AppGitConfigHelper) CloneRepos(ctx context.Context, templateRepo, cust return } - if err = ca.gitPlugin.Clone(reqRepo, customerRepo, token); err != nil { + if err = ca.gitClient.Clone(reqRepo, customerRepo, token); err != nil { os.RemoveAll(templateDir) os.RemoveAll(reqRepo) err = fmt.Errorf("failed to Clone user repo, err: %v", err) @@ -155,34 +152,19 @@ func (ca *AppGitConfigHelper) WaitForArgoCDToSync(ctx context.Context, ns, resNa return nil } -func (ca *AppGitConfigHelper) AddToGit(ctx context.Context, paramType, repoUrl, token string, createPR bool) error { - if err := ca.gitPlugin.Commit(".", "configure requested app", +func (ca *AppGitConfigHelper) AddToGit(ctx context.Context, paramType, repoUrl, token string) error { + if err := ca.gitClient.Commit(".", "configure requested app", ca.cfg.GitDefaultCommiterName, ca.cfg.GitDefaultCommiterEmail); err != nil { return fmt.Errorf("failed to commit the changes to user repo, err: %v", err) } - defaultBranch, err := ca.gitPlugin.GetDefaultBranchName() + defaultBranch, err := ca.gitClient.GetDefaultBranchName() if err != nil { return fmt.Errorf("failed to get default branch of user repo, err: %v", err) } - if createPR { - _, err = ca.createPR(ctx, repoUrl, ca.cfg.GitBranchName+"-"+paramType, defaultBranch, token) - if err != nil { - return fmt.Errorf("failed to create the PR on user repo, err: %v", err) - } - logger.Info("created PR, skiping push to default branch") - return nil - } - - if err := ca.gitPlugin.Push(defaultBranch, token); err != nil { + if err := ca.gitClient.Push(defaultBranch, token); err != nil { return fmt.Errorf("failed to get push to default branch, err: %v", err) } return nil } - -func (ca *AppGitConfigHelper) createPR(ctx context.Context, repoURL, commitBranch, baseBranch, token string) (string, error) { - op := github.NewOperation(token) - str := strings.Split(repoURL, "/") - return op.CreatePR(ctx, strings.TrimSuffix(str[len(str)-1], gitUrlSuffix), str[len(str)-2], "Configuring requested app", commitBranch, baseBranch, "") -} diff --git a/capten/config-worker/internal/crossplane/config_crossplane_app.go b/capten/config-worker/internal/crossplane/config_crossplane_app.go index ed2356d1..ec2650e3 100644 --- a/capten/config-worker/internal/crossplane/config_crossplane_app.go +++ b/capten/config-worker/internal/crossplane/config_crossplane_app.go @@ -97,7 +97,7 @@ func (cp *CrossPlaneApp) configureProjectAndApps(ctx context.Context, req *model } logger.Infof("updated resource configurations in cloned project %s", req.RepoURL) - err = cp.helper.AddToGit(ctx, req.Type, req.RepoURL, accessToken, false) + err = cp.helper.AddToGit(ctx, req.Type, req.RepoURL, accessToken) if err != nil { return string(agentmodel.WorkFlowStatusFailed), errors.WithMessage(err, "failed to add git repo") } diff --git a/capten/deployment-worker/internal/activities/activity.go b/capten/deployment-worker/internal/activities/activity.go index da35ebc4..b0ef9071 100644 --- a/capten/deployment-worker/internal/activities/activity.go +++ b/capten/deployment-worker/internal/activities/activity.go @@ -7,8 +7,7 @@ import ( "strings" "github.com/intelops/go-common/logging" - "github.com/kube-tarian/kad/capten/common-pkg/plugins" - workerframework "github.com/kube-tarian/kad/capten/common-pkg/worker-framework" + "github.com/kube-tarian/kad/capten/common-pkg/plugins/helm" "github.com/kube-tarian/kad/capten/model" ) @@ -19,10 +18,8 @@ var logger = logging.NewLogger() func (a *Activities) DeploymentInstallActivity(ctx context.Context, req *model.ApplicationDeployRequest) (model.ResponsePayload, error) { logger.Infof("Activity, name: %+v", req) - // e := activity.GetInfo(ctx) - // logger.Infof("activity info: %+v", e) - plugin, err := plugins.GetPlugin(req.PluginName, logger) + helmClient, err := helm.NewClient(logger) if err != nil { logger.Errorf("Get plugin failed: %v", err) return model.ResponsePayload{ @@ -31,15 +28,7 @@ func (a *Activities) DeploymentInstallActivity(ctx context.Context, req *model.A }, err } - deployerPlugin, ok := plugin.(workerframework.DeploymentWorker) - if !ok { - return model.ResponsePayload{ - Status: "Failed", - Message: json.RawMessage("{\"error\": \"not implemented deployer worker plugin\"}"), - }, fmt.Errorf("plugin not supports deployment activities") - } - - msg, err := deployerPlugin.Create(&model.CreteRequestPayload{ + msg, err := helmClient.Create(&model.CreteRequestPayload{ RepoName: req.RepoName, RepoURL: req.RepoURL, ChartName: req.ChartName, @@ -65,25 +54,17 @@ func (a *Activities) DeploymentInstallActivity(ctx context.Context, req *model.A func (a *Activities) DeploymentDeleteActivity(ctx context.Context, req *model.DeployerDeleteRequest) (model.ResponsePayload, error) { logger.Infof("Activity, name: %+v", req) - // e := activity.GetInfo(ctx) - // logger.Infof("activity info: %+v", e) - plugin, err := plugins.GetPlugin(req.PluginName, logger) + helmClient, err := helm.NewClient(logger) if err != nil { - logger.Errorf("Get plugin failed: %v", err) + logger.Errorf("Get helm client failed: %v", err) return model.ResponsePayload{ Status: "Failed", Message: json.RawMessage(fmt.Sprintf("{\"error\": \"%v\"}", strings.ReplaceAll(err.Error(), "\"", "\\\""))), }, err } - deployerPlugin, ok := plugin.(workerframework.DeploymentWorker) - if !ok { - return model.ResponsePayload{ - Status: "Failed", - Message: json.RawMessage(fmt.Sprintf("{\"error\": \"%v\"}", strings.ReplaceAll(err.Error(), "\"", "\\\""))), - }, fmt.Errorf("plugin not supports deployment activities") - } - msg, err := deployerPlugin.Delete(&model.DeleteRequestPayload{ + + msg, err := helmClient.Delete(&model.DeleteRequestPayload{ Namespace: req.Namespace, ReleaseName: req.ReleaseName, Timeout: req.Timeout, diff --git a/capten/go.mod b/capten/go.mod index 2862d82a..a4ce2916 100644 --- a/capten/go.mod +++ b/capten/go.mod @@ -10,7 +10,6 @@ require ( github.com/google/uuid v1.3.0 github.com/hashicorp/go-multierror v1.1.1 github.com/intelops/go-common v1.0.15 - github.com/json-iterator/go v1.1.12 github.com/kelseyhightower/envconfig v1.4.0 github.com/kube-tarian/kad/integrator v0.0.0-20230520105805-73f03d9dcfcc github.com/ory/client-go v1.1.44 @@ -35,6 +34,7 @@ require ( require ( github.com/cloudflare/circl v1.3.3 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/json-iterator/go v1.1.12 // indirect ) require (