Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: change persistent directory name to deterministic value #2006

Merged
merged 15 commits into from
Jan 8, 2024
Merged
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package object_attributes_provider

import (
"crypto/md5"
"encoding/hex"
"fmt"
"net"
"strconv"
Expand All @@ -26,8 +24,7 @@ const (
networkPrefix = "kt-"
apiContainerNamePrefix = "kurtosis-api"

artifactExpansionVolumeNameFragment = "files-artifact-expansion"
persistentServiceDirectoryNameFragment = "service-persistent-directory"
artifactExpansionVolumeNameFragment = "files-artifact-expansion"

artifactsExpanderContainerNameFragment = "files-artifacts-expander"
logsCollectorFragment = "kurtosis-logs-collector"
Expand Down Expand Up @@ -333,14 +330,8 @@ func (provider *dockerEnclaveObjectAttributesProviderImpl) ForSinglePersistentDi
return nil, stacktrace.Propagate(err, "An error occurred generating a UUID for the persistent directory volume for service '%v'", serviceUuidStr)
}

hasher := md5.New()
hasher.Write([]byte(serviceUUID))
hasher.Write([]byte(persistentKey))
persistentKeyHash := hex.EncodeToString(hasher.Sum(nil))

name, err := provider.getNameForEnclaveObject([]string{
persistentServiceDirectoryNameFragment,
persistentKeyHash,
string(persistentKey),
})
if err != nil {
return nil, stacktrace.Propagate(err, "An error occurred creating the files artifact expansion volume name object using GUID '%v' and service GUID '%v'", guidStr, serviceUuidStr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ const (

enclaveDataDirFragment = "enclave-data-dir"

persistentServiceDirectoryNameFragment = "service-persistent-directory"

traefikIngressRouterEntrypointsValue = "web"
)

Expand Down Expand Up @@ -264,7 +262,7 @@ func (provider *kubernetesEnclaveObjectAttributesProviderImpl) ForSinglePersiste
//No userServiceService annotations.
annotations := map[*kubernetes_annotation_key.KubernetesAnnotationKey]*kubernetes_annotation_value.KubernetesAnnotationValue{}

name, err := getKubernetesPersistentDirectoryName(persistentKeyHash)
name, err := getKubernetesPersistentDirectoryName(string(persistentKey))
if err != nil {
return nil, stacktrace.Propagate(err, "Failed to create service persistent directory name for hash: '%s'", persistentKeyHash)
}
Expand Down Expand Up @@ -329,12 +327,11 @@ func getKubernetesObjectName(
}

func getKubernetesPersistentDirectoryName(
persistentServiceDirectoryName string,
persistentKey string,
) (*kubernetes_object_name.KubernetesObjectName, error) {
name, err := getCompositeKubernetesObjectName(
[]string{
persistentServiceDirectoryNameFragment,
persistentServiceDirectoryName,
persistentKey,
})
return name, err
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
package service_directory

import "regexp"

const (
// PersistentKeyRegex implements RFC-1035 for naming persistent directory keys, namely:
h4ck3rk3y marked this conversation as resolved.
Show resolved Hide resolved
h4ck3rk3y marked this conversation as resolved.
Show resolved Hide resolved
// * contain at most 63 characters
// * contain only lowercase alphanumeric characters or '-'
// * start with an alphabetic character
// * end with an alphanumeric character
// The adoption of RFC-1035 is to maintain compatability with current Kubernetes service and pod naming standards:
// We use this over RFC-1035 as persistent data require 1035 to be followed
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
// https://kubernetes.io/docs/concepts/services-networking/service/
PersistentKeyRegex = "[a-z]([-a-z0-9]{0,61}[a-z0-9])?"
WordWrappedPersistentKeyRegex = "^" + PersistentKeyRegex + "$"
h4ck3rk3y marked this conversation as resolved.
Show resolved Hide resolved
)

var (
compiledWordWrappedPersistentKeyRegex = regexp.MustCompile(WordWrappedPersistentKeyRegex)
)

type DirectoryPersistentKey string
type DirectoryPersistentSize int64

Expand All @@ -17,3 +37,7 @@ func NewPersistentDirectories(persistentDirectories map[string]PersistentDirecto
ServiceDirpathToPersistentDirectory: persistentDirectories,
}
}

func IsPersistentKeyValid(persistentKey DirectoryPersistentKey) bool {
h4ck3rk3y marked this conversation as resolved.
Show resolved Hide resolved
return compiledWordWrappedPersistentKeyRegex.MatchString(string(persistentKey))
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_directory"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper"
Expand Down Expand Up @@ -70,6 +71,14 @@ func validateSingleService(validatorEnvironment *startosis_validator.ValidatorEn
return startosis_errors.NewValidationError(invalidServiceNameErrorText(serviceName))
}

if persistentDirectories := serviceConfig.GetPersistentDirectories(); persistentDirectories != nil {
for _, directory := range persistentDirectories.ServiceDirpathToPersistentDirectory {
if !service_directory.IsPersistentKeyValid(directory.PersistentKey) {
return startosis_errors.NewValidationError(invalidPersistentKeyErrorText(directory.PersistentKey))
}
}
}

if validatorEnvironment.DoesServiceNameExist(serviceName) == startosis_validator.ComponentCreatedOrUpdatedDuringPackageRun {
return startosis_errors.NewValidationError("There was an error validating '%s' as service with the name '%s' already exists inside the package. Adding two different services with the same name isn't allowed; we recommend prefixing/suffixing the two service names or using two different names entirely.", AddServiceBuiltinName, serviceName)
}
Expand Down Expand Up @@ -117,6 +126,16 @@ func invalidServiceNameErrorText(
)
}

func invalidPersistentKeyErrorText(
persistentKey service_directory.DirectoryPersistentKey,
) string {
return fmt.Sprintf(
"Persistent Key '%v' is invalid as it contains disallowed characters. Persistent Key must adhere to the RFC 1035 standard, specifically implementing this regex and be 1-63 characters long: %s. This means the service name must only contain lowercase alphanumeric characters or '-', and must start with a lowercase alphabet and end with a lowercase alphanumeric character.",
h4ck3rk3y marked this conversation as resolved.
Show resolved Hide resolved
persistentKey,
service_directory.WordWrappedPersistentKeyRegex,
)
}

func replaceMagicStrings(
runtimeValueStore *runtime_value_store.RuntimeValueStore,
serviceName service.ServiceName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def run(plan):
image=IMAGE,
files={
"/data": Directory(
persistent_key="persistent_data",
persistent_key="persistent-data",
),
},
min_cpu=%d,
Expand Down
Loading