mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
Allow artifacts checksum interpolation
Fixes https://github.com/hashicorp/nomad/issues/4814
This commit is contained in:
@@ -26,3 +26,8 @@ func ReplaceEnv(arg string, environments ...map[string]string) string {
|
||||
func ReplaceEnvWithPlaceHolder(arg string, placeholder string) string {
|
||||
return envRe.ReplaceAllString(arg, placeholder)
|
||||
}
|
||||
|
||||
// ContainsEnv takes an arg and returns true if if contains an environment variable reference
|
||||
func ContainsEnv(arg string) bool {
|
||||
return envRe.MatchString(arg)
|
||||
}
|
||||
|
||||
@@ -75,3 +75,30 @@ func TestArgs_ReplaceEnv_Chained(t *testing.T) {
|
||||
t.Fatalf("ReplaceEnv(%v, %v) returned %#v; want %#v", input, envVars, act, exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArgs_ContainsEnv(t *testing.T) {
|
||||
positiveCases := []string{
|
||||
"test-${env_var}",
|
||||
}
|
||||
for _, c := range positiveCases {
|
||||
t.Run(fmt.Sprintf("positive case: %v", c), func(t *testing.T) {
|
||||
if !ContainsEnv(c) {
|
||||
t.Fatalf("ContainsEnv(%v) returned false; want true", c)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
negativeCases := []string{
|
||||
"test",
|
||||
"test-$",
|
||||
"test-${asdf",
|
||||
}
|
||||
for _, c := range negativeCases {
|
||||
t.Run(fmt.Sprintf("positive case: %v", c), func(t *testing.T) {
|
||||
if ContainsEnv(c) {
|
||||
t.Fatalf("ContainsEnv(%v) returned true; want false", c)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6155,51 +6155,64 @@ func (ta *TaskArtifact) Validate() error {
|
||||
}
|
||||
|
||||
// Verify the checksum
|
||||
if check, ok := ta.GetterOptions["checksum"]; ok {
|
||||
check = strings.TrimSpace(check)
|
||||
if check == "" {
|
||||
mErr.Errors = append(mErr.Errors, fmt.Errorf("checksum value cannot be empty"))
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
parts := strings.Split(check, ":")
|
||||
if l := len(parts); l != 2 {
|
||||
mErr.Errors = append(mErr.Errors, fmt.Errorf(`checksum must be given as "type:value"; got %q`, check))
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
checksumVal := parts[1]
|
||||
checksumBytes, err := hex.DecodeString(checksumVal)
|
||||
if err != nil {
|
||||
mErr.Errors = append(mErr.Errors, fmt.Errorf("invalid checksum: %v", err))
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
checksumType := parts[0]
|
||||
expectedLength := 0
|
||||
switch checksumType {
|
||||
case "md5":
|
||||
expectedLength = md5.Size
|
||||
case "sha1":
|
||||
expectedLength = sha1.Size
|
||||
case "sha256":
|
||||
expectedLength = sha256.Size
|
||||
case "sha512":
|
||||
expectedLength = sha512.Size
|
||||
default:
|
||||
mErr.Errors = append(mErr.Errors, fmt.Errorf("unsupported checksum type: %s", checksumType))
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
if len(checksumBytes) != expectedLength {
|
||||
mErr.Errors = append(mErr.Errors, fmt.Errorf("invalid %s checksum: %v", checksumType, checksumVal))
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
if err := ta.validateChecksum(); err != nil {
|
||||
mErr.Errors = append(mErr.Errors, err)
|
||||
}
|
||||
|
||||
return mErr.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (ta *TaskArtifact) validateChecksum() error {
|
||||
check, ok := ta.GetterOptions["checksum"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// job struct validation occurs before interpolation resolution can be effective
|
||||
// skip checking if checksum contain variable reference, and artifacts fetching will
|
||||
// eventually fail at pick up time if checksum is indeed invalid
|
||||
if args.ContainsEnv(check) {
|
||||
return nil
|
||||
}
|
||||
|
||||
check = strings.TrimSpace(check)
|
||||
if check == "" {
|
||||
return fmt.Errorf("checksum value cannot be empty")
|
||||
}
|
||||
|
||||
parts := strings.Split(check, ":")
|
||||
if l := len(parts); l != 2 {
|
||||
return fmt.Errorf(`checksum must be given as "type:value"; got %q`, check)
|
||||
}
|
||||
|
||||
checksumVal := parts[1]
|
||||
checksumBytes, err := hex.DecodeString(checksumVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid checksum: %v", err)
|
||||
}
|
||||
|
||||
checksumType := parts[0]
|
||||
expectedLength := 0
|
||||
switch checksumType {
|
||||
case "md5":
|
||||
expectedLength = md5.Size
|
||||
case "sha1":
|
||||
expectedLength = sha1.Size
|
||||
case "sha256":
|
||||
expectedLength = sha256.Size
|
||||
case "sha512":
|
||||
expectedLength = sha512.Size
|
||||
default:
|
||||
return fmt.Errorf("unsupported checksum type: %s", checksumType)
|
||||
}
|
||||
|
||||
if len(checksumBytes) != expectedLength {
|
||||
return fmt.Errorf("invalid %s checksum: %v", checksumType, checksumVal)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
ConstraintDistinctProperty = "distinct_property"
|
||||
ConstraintDistinctHosts = "distinct_hosts"
|
||||
|
||||
@@ -2672,6 +2672,15 @@ func TestTaskArtifact_Validate_Checksum(t *testing.T) {
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
&TaskArtifact{
|
||||
GetterSource: "foo.com",
|
||||
GetterOptions: map[string]string{
|
||||
"checksum": "md5:${ARTIFACT_CHECKSUM}",
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
|
||||
Reference in New Issue
Block a user