This repository has been archived by the owner on May 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 54
/
credential_add.go
144 lines (119 loc) · 3.17 KB
/
credential_add.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/cnabio/duffle/pkg/duffle/home"
"github.com/cnabio/cnab-go/credentials"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
const credentialAddDesc = `
This command takes a path to a file, validates that the file contains a valid credential set, and adds the credential sets to duffle.
It is also possible to pass in multiple paths to this command to conveniently add multiple credential sets.
`
type credentialAddCmd struct {
paths []string
home home.Home
out io.Writer
}
func newCredentialAddCmd(w io.Writer) *cobra.Command {
add := &credentialAddCmd{out: w}
cmd := &cobra.Command{
Use: "add [PATH]",
Short: "add one or more credential sets",
Long: credentialAddDesc,
RunE: func(cmd *cobra.Command, args []string) error {
add.home = home.Home(homePath())
if len(args) < 1 {
return errors.New("This command requires at least 1 argument: path to credential set")
}
add.paths = args
return add.run()
},
}
return cmd
}
func (add *credentialAddCmd) run() error {
addErrors := []string{}
for _, path := range add.paths {
fi, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
doesNotExist := fmt.Sprintf("File (%s) does not exist", path)
addErrors = append(addErrors, doesNotExist)
continue
} else {
addErrors = append(addErrors, err.Error())
continue
}
}
if fi.IsDir() {
dirErr := fmt.Sprintf("%s is a directory. Enter path to a credential set file", path)
addErrors = append(addErrors, dirErr)
continue
} else {
dest := filepath.Join(add.home.Credentials(), fi.Name())
err = addCredentialSet(dest, path)
if err != nil {
addErrors = append(addErrors, err.Error())
continue
}
}
}
if len(addErrors) > 0 {
return fmt.Errorf(strings.Join(addErrors, "\n"))
}
return nil
}
func addCredentialSet(dest, path string) error {
// validate file to be credential set
cs, err := credentials.Load(path)
if err != nil {
return fmt.Errorf("%s is not a valid credential set", path)
}
if err := fileNameMatchesSetName(path, cs.Name); err != nil {
return err
}
// check if it already exists
if _, err := os.Stat(dest); !os.IsNotExist(err) {
return fmt.Errorf("Credential set (%s) already exists", cs.Name)
}
if err := copyCredentialSetFile(dest, path); err != nil {
return err
}
log.Debugf("Successfully added credential set: %s", cs.Name)
return nil
}
func copyCredentialSetFile(dest, path string) error {
from, err := os.Open(path)
if err != nil {
return err
}
defer from.Close()
to, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE, 0600)
if err != nil {
return err
}
defer to.Close()
_, err = io.Copy(to, from)
return err
}
func fileNameMatchesSetName(path, name string) error {
base := filepath.Base(path)
parts := strings.Split(base, ".")
computedName := ""
len := len(parts)
if len > 1 {
computedName = strings.Join(parts[0:len-1], ".")
} else {
return fmt.Errorf("%s does not have valid .yaml/.yml file extension", path)
}
if computedName != name {
return fmt.Errorf("file name (%s) does not match credential set name (%s)", computedName, name)
}
return nil
}