Skip to content

Commit beb97c8

Browse files
authored
feat: update helm-repo-updater to be able to use a string input for SSH Private Key (#28)
1 parent 36b965c commit beb97c8

File tree

9 files changed

+162
-36
lines changed

9 files changed

+162
-36
lines changed

.github/workflows/release.yaml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,11 @@ jobs:
1919
- name: Unshallow
2020
run: git fetch --prune --unshallow
2121

22-
- name: Set Docker Image Registry Env
23-
run: |
24-
echo DOCKER_IMAGE_REGISTRY=$(echo "${{ env.REGISTRY}}/${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
25-
26-
2722
- name: Set up Go
2823
uses: actions/setup-go@v1
2924
with:
3025
go-version: 1.17.x
3126

32-
- name: Run GoReleaser
33-
uses: goreleaser/goreleaser-action@v1
34-
with:
35-
version: latest
36-
args: release --rm-dist
37-
env:
38-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39-
4027
- name: Get the version to publish
4128
id: get_version
4229
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
@@ -55,3 +42,11 @@ jobs:
5542
run: make publish
5643
env:
5744
VERSION: ${{ steps.get_version.outputs.VERSION }}
45+
46+
- name: Run GoReleaser to publish release
47+
uses: goreleaser/goreleaser-action@v2
48+
with:
49+
version: v1.6.1
50+
args: release --rm-dist
51+
env:
52+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ This repo aims to manage the development of `helm-repo-updater`, a CLI tool whos
4040
Flags:
4141
--app-name string app name
4242
--dry-run run in dry-run mode. If set to true, do not perform any changes
43-
--git-branch string branch (default "develop")
44-
--git-commit-email string E-Mail address to use for Git commits
43+
--git-branch string git repo branch (default "develop")
44+
--git-commit-email string e-mail address to use for Git commits
4545
--git-commit-user string Username to use for Git commits
4646
--git-dir string file eg. /production/charts/
4747
--git-file string file eg. values.yaml
@@ -50,7 +50,8 @@ This repo aims to manage the development of `helm-repo-updater`, a CLI tool whos
5050
--helm-key-values stringToString helm key-values sets (default [])
5151
-h, --help help for run
5252
--logLevel string set the loglevel to one of trace|debug|info|warn|error (default "info")
53-
--ssh-private-key string ssh private key (only using
53+
--ssh-private-key string ssh private key
54+
--ssh-private-key-inline ssh private key inline creation, if true it will use ssh-private-key as input for create ssh private key file in temporal directory
5455

5556
Global Flags:
5657
--config string config file (default is $HOME/.helm-repo-updater.yaml)

cmd/run.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ const (
3131
AppName = "app-name"
3232
// SSHPrivateKey is the location of the SSH private key used for auth
3333
SSHPrivateKey = "ssh-private-key"
34+
// UseSSHPrivateKeyAsInline indicates if the SSHPrivateKey is going to be created based in a string provided
35+
UseSSHPrivateKeyAsInline = "use-ssh-private-key-as-inline"
3436
// DryRun is going to indicate if the changes are going to be committed or not
3537
DryRun = "dry-run"
3638
// LogLevel will indicate the log level
@@ -74,6 +76,8 @@ var runCmd = &cobra.Command{
7476
}
7577

7678
var updateApps []updater.ChangeEntry
79+
var tpl *template.Template
80+
var err error
7781
for k, v := range helmKVs {
7882
updateApps = append(updateApps, updater.ChangeEntry{
7983
Key: k,
@@ -95,15 +99,13 @@ var runCmd = &cobra.Command{
9599

96100
logCtx := log.WithContext().AddField("application", appName)
97101

98-
if tpl, err := template.New("commitMessage").Parse(git.DefaultGitCommitMessage); err != nil {
102+
if tpl, err = template.New("commitMessage").Parse(git.DefaultGitCommitMessage); err != nil {
99103
logCtx.Fatalf("could not parse commit message template: %v", err)
100104

101105
return
102-
} else {
103-
logCtx.Debugf("Successfully parsed commit message template")
104-
105-
gitConf.Message = tpl
106106
}
107+
logCtx.Debugf("Successfully parsed commit message template")
108+
gitConf.Message = tpl
107109

108110
cfg = updater.HelmUpdaterConfig{
109111
DryRun: dryRun,
@@ -115,7 +117,7 @@ var runCmd = &cobra.Command{
115117
GitConf: gitConf,
116118
}
117119

118-
if err := runImageUpdater(cfg); err != nil {
120+
if err = runImageUpdater(cfg); err != nil {
119121
logCtx.Errorf("Error trying to update the %s application: %v", appName, err)
120122
}
121123
},
@@ -146,14 +148,15 @@ func init() {
146148
rootCmd.AddCommand(runCmd)
147149

148150
runCmd.Flags().String(GitCommitUser, "", "Username to use for Git commits")
149-
runCmd.Flags().String(GitCommitEmail, "", "E-Mail address to use for Git commits")
151+
runCmd.Flags().String(GitCommitEmail, "", "e-mail address to use for Git commits")
150152
runCmd.Flags().String(GitPassword, "", "Password for github user")
151-
runCmd.Flags().String(GitBranch, "develop", "branch")
153+
runCmd.Flags().String(GitBranch, "develop", "git repo branch")
152154
runCmd.Flags().String(GitRepoURL, "", "git repo url")
153155
runCmd.Flags().String(GitFile, "", "file eg. values.yaml")
154156
runCmd.Flags().String(GitDir, "", "file eg. /production/charts/")
155157
runCmd.Flags().String(AppName, "", "app name")
156158
runCmd.Flags().String(SSHPrivateKey, "", "ssh private key")
159+
runCmd.Flags().Bool(UseSSHPrivateKeyAsInline, false, "ssh private key inline creation, if true it will use ssh-private-key as input for create ssh private key file in temporal directory")
157160
runCmd.Flags().Bool(DryRun, false, "run in dry-run mode. If set to true, do not perform any changes")
158161
runCmd.Flags().String(LogLevel, "info", "set the loglevel to one of trace|debug|info|warn|error")
159162
runCmd.Flags().StringToString(HelmKeyValues, nil, "helm key-values sets")

goreleaser.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ builds:
1414
- amd64
1515
- arm64
1616

17+
release:
18+
github:
19+
owner: DocPlanner
20+
name: helm-repo-updater
21+
footer: |
22+
## Docker Images
23+
- `docplanner/helm-repo-updater:{{ trimprefix .Tag "v" }}`
24+
- `docplanner/helm-repo-updater:latest`
25+
- `ghcr.io/docplanner/helm-repo-updater:{{ trimprefix .Tag "v" }}`
26+
- `ghcr.io/docplanner/helm-repo-updater:latest`
27+
1728
changelog:
1829
sort: desc
1930

internal/app/git/creds.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package git
22

33
import (
44
"fmt"
5+
"os"
56
"regexp"
67

78
"github.com/docplanner/helm-repo-updater/internal/app/log"
9+
app_utils "github.com/docplanner/helm-repo-updater/internal/app/utils"
810
"github.com/go-git/go-git/v5/plumbing/transport"
911
"github.com/go-git/go-git/v5/plumbing/transport/http"
1012
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
@@ -17,10 +19,11 @@ var (
1719

1820
// Credentials is a git credential config
1921
type Credentials struct {
20-
Username string
21-
Password string
22-
Email string
23-
SSHPrivKey string
22+
Username string
23+
Password string
24+
Email string
25+
SSHPrivKey string
26+
SSHPrivKeyFileInline bool
2427
}
2528

2629
// NewGitCreds returns credentials for use with go-git library
@@ -57,8 +60,20 @@ func isHTTPSURL(url string) bool {
5760

5861
// generateAuthForSSH generate the necessary public keys as auth for git repository using
5962
// the provided privateKeyFile containing a valid SSH private key
60-
func generateAuthForSSH(repoURL string, userName string, privateKeyFile string, password string) (ssh.AuthMethod, error) {
61-
publicKeys, err := ssh.NewPublicKeysFromFile("git", privateKeyFile, password)
63+
func generateAuthForSSH(repoURL string, userName string, privateKeyFile string, SSHPrivKeyFileInline bool, password string) (ssh.AuthMethod, error) {
64+
sshPrivKeyFileName := privateKeyFile
65+
if SSHPrivKeyFileInline {
66+
sshPrivKeyFile, err := app_utils.CreateAndWriteContentInTempFile("sshPrivKey", privateKeyFile)
67+
if err != nil {
68+
return nil, err
69+
}
70+
sshPrivKeyFileName = sshPrivKeyFile.Name()
71+
// close and remove the temporary file at the end of the program
72+
defer sshPrivKeyFile.Close()
73+
defer os.Remove(sshPrivKeyFileName)
74+
log.Infof("Generated file in %s location with content of SSH private key provided as input", sshPrivKeyFileName)
75+
}
76+
publicKeys, err := ssh.NewPublicKeysFromFile("git", sshPrivKeyFileName, password)
6277
if err != nil {
6378
log.Warnf("generate publickeys failed: %s\n", err.Error())
6479
return nil, err
@@ -69,7 +84,7 @@ func generateAuthForSSH(repoURL string, userName string, privateKeyFile string,
6984
// fromSSH generate a valid credentials using ssh key
7085
func (c Credentials) fromSSH(repoURL string, password string) (ssh.AuthMethod, error) {
7186
if c.allowsSSHAuth() {
72-
sshPublicKeys, err := generateAuthForSSH(repoURL, c.Username, c.SSHPrivKey, password)
87+
sshPublicKeys, err := generateAuthForSSH(repoURL, c.Username, c.SSHPrivKey, c.SSHPrivKeyFileInline, password)
7388
if err != nil {
7489
return nil, err
7590
}

internal/app/git/creds_test.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,17 @@ const (
1414
validGitCredentialsUsername = "test-user"
1515
validGitCredentialsPassword = "test-password"
1616
validSSHPrivKeyRelativeRoute = "/test-git-server/private_keys/helm-repo-updater-test"
17-
validGitRepoSSHURL = "git@github.com:kubernetes/kubernetes.git"
18-
validGitRepoHTTPSURL = "https://github.com/kubernetes/kubernetes.git"
19-
invalidGitRepoURL = "github.com/kubernetes/kubernetes.git"
20-
invalidPrivKeyRoute = "/tmp/key-dont-exists"
17+
validSSHPrivKeyString = `-----BEGIN OPENSSH PRIVATE KEY-----
18+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
19+
QyNTUxOQAAACCNAv45QMrXuGuWk7uadYNOlL1B2q/g2pw1g+xP5oD/EQAAAJjmelMZ5npT
20+
GQAAAAtzc2gtZWQyNTUxOQAAACCNAv45QMrXuGuWk7uadYNOlL1B2q/g2pw1g+xP5oD/EQ
21+
AAAEA8ubLuVW5jc+Q9a2divLLVfm0Up+eus/9f7/HvACUD2o0C/jlAyte4a5aTu5p1g06U
22+
vUHar+DanDWD7E/mgP8RAAAAFWRldm9wc0Bkb2NwbGFubmVyLmNvbQ==
23+
-----END OPENSSH PRIVATE KEY-----`
24+
validGitRepoSSHURL = "git@github.com:kubernetes/kubernetes.git"
25+
validGitRepoHTTPSURL = "https://github.com/kubernetes/kubernetes.git"
26+
invalidGitRepoURL = "github.com/kubernetes/kubernetes.git"
27+
invalidPrivKeyRoute = "/tmp/key-dont-exists"
2128
)
2229

2330
func TestNewCredsSSHURLSSHPrivKey(t *testing.T) {
@@ -44,6 +51,25 @@ func TestNewCredsSSHURLSSHPrivKey(t *testing.T) {
4451
assert.DeepEqual(t, creds.String(), expectedCredsString)
4552
}
4653

54+
func TestNewCredsSSHURLSSHPrivKeyFromString(t *testing.T) {
55+
g := Credentials{
56+
Username: validGitCredentialsUsername,
57+
Email: validGitCredentialsEmail,
58+
SSHPrivKey: validSSHPrivKeyString,
59+
SSHPrivKeyFileInline: true,
60+
}
61+
62+
repoURL := validGitRepoSSHURL
63+
64+
creds, err := g.NewGitCreds(repoURL, g.Password)
65+
if err != nil {
66+
log.Fatal(err)
67+
}
68+
69+
expectedCredsString := "user: git, name: ssh-public-keys"
70+
assert.DeepEqual(t, creds.String(), expectedCredsString)
71+
}
72+
4773
func TestNewCredsHTPPSURLUsernamePassword(t *testing.T) {
4874

4975
g := Credentials{

internal/app/updater/commit.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,6 @@ func commitChangesGit(cfg HelmUpdaterConfig, write changeWriter) (*[]ChangeEntry
285285
var apps []ChangeEntry
286286

287287
logCtx := log.WithContext().AddField("application", cfg.AppName)
288-
289288
creds, err := cfg.GitCredentials.NewGitCreds(cfg.GitConf.RepoURL, cfg.GitCredentials.Password)
290289
if err != nil {
291290
return nil, fmt.Errorf("could not get creds for repo '%s': %v", cfg.AppName, err)

internal/app/updater/commit_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package updater
22

33
import (
44
"fmt"
5+
"io/ioutil"
56
"log"
67
"os"
78
"testing"
@@ -181,6 +182,63 @@ func TestUpdateApplicationDryRun(t *testing.T) {
181182
assert.DeepEqual(t, *apps, changeEntries)
182183
}
183184

185+
func TestUpdateApplicationDryRunSSHPrivKeyString(t *testing.T) {
186+
sshPrivKeyRoute, err := app_utils.GetRouteRelativePath(2, validSSHPrivKeyRelativeRoute)
187+
if err != nil {
188+
log.Fatal(err)
189+
}
190+
content, err := ioutil.ReadFile(*sshPrivKeyRoute)
191+
if err != nil {
192+
log.Fatal(err)
193+
}
194+
195+
// Convert []byte to string
196+
validSSHPrivKeyString := string(content)
197+
gCred := git.Credentials{
198+
Email: validGitCredentialsEmail,
199+
Username: validGitCredentialsUsername,
200+
SSHPrivKey: validSSHPrivKeyString,
201+
SSHPrivKeyFileInline: true,
202+
}
203+
204+
validGitRepoURL := getSSHRepoHostnameAndPort() + validGitRepoRoute
205+
206+
gConf := git.Conf{
207+
RepoURL: validGitRepoURL,
208+
Branch: validGitRepoBranch,
209+
File: "",
210+
}
211+
212+
changeEntry := ChangeEntry{
213+
OldValue: "1.0.0",
214+
NewValue: "1.1.0",
215+
File: "",
216+
Key: ".image.tag",
217+
}
218+
changeEntries := []ChangeEntry{
219+
changeEntry,
220+
}
221+
222+
cfg := HelmUpdaterConfig{
223+
DryRun: true,
224+
LogLevel: "info",
225+
AppName: validHelmAppName,
226+
UpdateApps: changeEntries,
227+
File: validHelmAppFileToChange,
228+
GitCredentials: &gCred,
229+
GitConf: &gConf,
230+
}
231+
232+
syncState := NewSyncIterationState()
233+
apps, err := UpdateApplication(cfg, syncState)
234+
235+
if err != nil {
236+
log.Fatal(err)
237+
}
238+
239+
assert.DeepEqual(t, *apps, changeEntries)
240+
}
241+
184242
func TestUpdateApplicationDryRunInvalidFile(t *testing.T) {
185243

186244
sshPrivKeyRoute, err := app_utils.GetRouteRelativePath(2, validSSHPrivKeyRelativeRoute)

internal/app/utils/route_utils.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,21 @@ func GetRouteRelativePath(numRelativePath int, relativePath string) (*string, er
1919
finalPath = finalPath + relativePath
2020
return &finalPath, nil
2121
}
22+
23+
// CreateAndWriteContentInTempFile writes the string content in a temporary file
24+
// based in a pattern and creating the file in the default tmpDir of the machine
25+
func CreateAndWriteContentInTempFile(tempFilePattern string, content string) (*os.File, error) {
26+
// create and open a temporary file
27+
f, err := os.CreateTemp(os.TempDir(), tempFilePattern)
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
// write data to the temporary file
33+
data := []byte(content)
34+
if _, err := f.Write(data); err != nil {
35+
return nil, err
36+
}
37+
38+
return f, nil
39+
}

0 commit comments

Comments
 (0)