Skip to content

Commit

Permalink
Merge branch 'add-github-support' into 'main'
Browse files Browse the repository at this point in the history
Add github support

See merge request openlizz/lizz!4
  • Loading branch information
Remi Calizzano committed Aug 31, 2022
2 parents bed8ff9 + a60d1af commit f8b90a8
Show file tree
Hide file tree
Showing 15 changed files with 963 additions and 17 deletions.
273 changes: 273 additions & 0 deletions cmd/add_github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
/*
Copyright © 2022 Rémi Calizzano <remi.calizzano@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd

import (
"context"
"fmt"
"os"
"time"

"github.com/spf13/cobra"
"gitlab.com/openlizz/lizz/internal/github"
"gitlab.com/openlizz/lizz/internal/provider"
"gitlab.com/openlizz/lizz/internal/repo"
"gitlab.com/openlizz/lizz/internal/yaml"
)

var addGithubCmd = &cobra.Command{
Use: "github",
Short: "",
Long: ``,
RunE: addGithubCmdRun,
}

type addGithubFlags struct {
owner string
fleet string
destination string
interval time.Duration
personal bool
hostname string
teams []string
readWriteKey bool
reconcile bool
}

var addGithubArgs addGithubFlags

func init() {
addGithubCmd.Flags().StringVar(&addGithubArgs.owner, "owner", "", "GitHub user or organization name")
addGithubCmd.Flags().StringVar(&addGithubArgs.fleet, "fleet", "", "GitHub repository name of the fleet repository")
addGithubCmd.Flags().StringVar(&addGithubArgs.destination, "destination", "", "GitHub repository name where to push the application repository")
addGithubCmd.Flags().
StringSliceVar(&addGithubArgs.teams, "team", []string{}, "GitHub team and the access to be given to it(team:maintain). Defaults to maintainer access if no access level is specified (also accepts comma-separated values)")
addGithubCmd.Flags().BoolVar(&addGithubArgs.personal, "personal", false, "if true, the owner is assumed to be a GitHub user; otherwise an org")
addGithubCmd.Flags().DurationVar(&addGithubArgs.interval, "interval", time.Minute, "sync interval")
addGithubCmd.Flags().StringVar(&addGithubArgs.hostname, "hostname", github.DefaultDomain, "GitHub hostname")
addGithubCmd.Flags().BoolVar(&addGithubArgs.readWriteKey, "read-write-key", false, "if true, the deploy key is configured with read/write permissions")
addGithubCmd.Flags().BoolVar(&addGithubArgs.reconcile, "reconcile", false, "if true, the configured options are also reconciled if the repository already exists")

addCmd.AddCommand(addGithubCmd)
}

func addGithubCmdRun(cmd *cobra.Command, args []string) error {
logger.V(0).Infof("Add new application...")

ghToken, err := github.GetToken()
if err != nil {
return err
}

var caBundle []byte
if addArgs.caFile != "" {
var err error
caBundle, err = os.ReadFile(addArgs.caFile)
if err != nil {
return fmt.Errorf("unable to read TLS CA file: %w", err)
}
}

// Build GitHub provider
providerCfg := provider.Config{
Provider: provider.GitProviderGitHub,
Hostname: addGithubArgs.hostname,
Token: ghToken,
CaBundle: caBundle,
}
providerClient, err := provider.BuildGitProvider(providerCfg)
if err != nil {
return err
}

applicationRepo, err := repo.CloneApplicationRepo(
&repo.CloneOptions{
URL: addArgs.originUrl,
Branch: addArgs.originBranch,
Username: addGithubArgs.owner,
Password: ghToken,
PrivateKeyFile: addArgs.privateKeyFile,
Timeout: rootArgs.timeout,
CaBundle: caBundle,
},
status,
)
if err != nil {
return err
}
head, err := applicationRepo.Git().Head()
if err != nil {
return err
}

clusterRepo, err := repo.CloneClusterRepo(
&repo.CloneOptions{
RepositoryName: addGithubArgs.fleet,
Owner: addGithubArgs.owner,
Branch: addArgs.fleetBranch,
Username: addGithubArgs.owner,
Password: ghToken,
PrivateKeyFile: addArgs.privateKeyFile,
Timeout: rootArgs.timeout,
Personal: addGithubArgs.personal,
Reconcile: addGithubArgs.reconcile,
Teams: mapTeamSlice(addGithubArgs.teams, github.DefaultPermission),
// CaBundle: caBundle,
// SshHostname: addArgs.sshHostname,
Provider: providerClient,
},
status,
)
if err != nil {
return err
}
err = clusterRepo.OpenClusterConfig(status)
if err != nil {
return err
}
err = applicationRepo.RenderApplicationConfig(
addArgs.values,
clusterRepo.Config(),
&repo.CloneOptions{
Username: addGithubArgs.owner,
Password: ghToken,
PrivateKeyFile: addArgs.privateKeyFile,
Timeout: rootArgs.timeout,
Personal: addGithubArgs.personal,
Reconcile: addGithubArgs.reconcile,
Teams: mapTeamSlice(addGithubArgs.teams, github.DefaultPermission),
CaBundle: caBundle,
SshHostname: addArgs.sshHostname,
Provider: providerClient,
},
status,
)
if err != nil {
return err
}
if addArgs.applicationName != "" {
applicationRepo.Config().Name = addArgs.applicationName
}
if addArgs.applicationNamespace != "" {
applicationRepo.Config().Namespace = addArgs.applicationNamespace
}
originUrl, transportType, err := repo.UniversalURL(addArgs.originUrl)
if err != nil {
return err
}
applicationRepo.Config().Repository = originUrl
applicationRepo.Config().TransportType = transportType
applicationRepo.Config().Sha = head
alreadyInstalled := false
err = applicationRepo.Config().Check(clusterRepo.Config(), alreadyInstalled, status)
if err != nil {
return err
}
err = applicationRepo.Render(repo.Repository{
Owner: addGithubArgs.owner,
Name: addGithubArgs.destination,
Branch: addArgs.destinationBranch,
}, addGithubArgs.owner, ghToken, status)
if err != nil {
return err
}
err = applicationRepo.Encrypt(clusterRepo.Config(), status)
if err != nil {
return err
}
transportType = "ssh"
if addArgs.tokenAuth == true {
transportType = "https"
}
destinationUrl, repository, err := repo.Create(&repo.CreateOptions{
RepositoryName: addGithubArgs.destination,
Owner: addGithubArgs.owner,
TransportType: transportType,
Branch: addArgs.destinationBranch,
Timeout: rootArgs.timeout,
Personal: addGithubArgs.personal,
Reconcile: addGithubArgs.reconcile,
Teams: mapTeamSlice(addGithubArgs.teams, github.DefaultPermission),
SshHostname: addArgs.sshHostname,
Provider: providerClient,
}, status)
if err != nil {
return err
}
applicationRepo.Git().SetAuth(addGithubArgs.owner, ghToken)
err = applicationRepo.CommitPush(
addArgs.authorName,
addArgs.authorEmail,
"[add application] Create application repository for "+applicationRepo.Config().Name,
destinationUrl,
addArgs.destinationBranch,
rootArgs.timeout,
status,
)
if err != nil {
return err
}
publicKey, err := clusterRepo.AddApplication(
destinationUrl,
addArgs.destinationBranch,
"github",
addArgs.destinationPrivate,
applicationRepo.Config(),
addArgs.clusterRole,
addArgs.decryptionSecret,
addArgs.path,
&yaml.SourceSecretOptions{
Namespace: applicationRepo.Config().Namespace,
Name: addArgs.sourceSecretName,
Username: "git",
Password: ghToken,
TokenAuth: addArgs.tokenAuth,
CaFile: addArgs.caFile,
KeyAlgorithm: addArgs.keyAlgorithm,
KeyRSABits: addArgs.keyRSABits,
KeyECDSACurve: addArgs.keyECDSACurve,
Hostname: addGithubArgs.hostname,
SshHostname: addArgs.sshHostname,
PrivateKeyFile: addArgs.privateKeyFile,
PlainProvider: false,
},
status,
)
if err != nil {
return err
}
if addArgs.destinationPrivate == true {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
err = reconcileDeployKey(ctx, publicKey, repository)
if err != nil {
return err
}
}
err = clusterRepo.CommitPush(
addArgs.authorName,
addArgs.authorEmail,
"[add application] Add "+applicationRepo.Config().Name+" to the cluster",
"",
addArgs.fleetBranch,
rootArgs.timeout,
status,
)
if err != nil {
return err
}
return nil
}
4 changes: 3 additions & 1 deletion cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -30,6 +30,7 @@ type initFlags struct {
originBranch string
destinationBranch string
destinationPrivate bool
sshHostname string
caFile string
privateKeyFile string

Expand All @@ -44,6 +45,7 @@ func init() {
initCmd.PersistentFlags().StringVar(&initArgs.originBranch, "origin-branch", "main", "Git branch of the repository")
initCmd.PersistentFlags().StringVar(&initArgs.destinationBranch, "destination-branch", "main", "Git branch of the destination repository")
initCmd.PersistentFlags().BoolVar(&initArgs.destinationPrivate, "private", true, "if true, the repository is setup or configured as private")
initCmd.PersistentFlags().StringVar(&initArgs.sshHostname, "ssh-hostname", "", "SSH hostname, to be used when the SSH host differs from the HTTPS one")
initCmd.PersistentFlags().StringVar(&initArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
initCmd.PersistentFlags().StringVar(&initArgs.privateKeyFile, "private-key-file", "", "path to a private key file used for authenticating to the Git SSH server")

Expand Down
Loading

0 comments on commit f8b90a8

Please sign in to comment.