diff --git a/pkg/component/registrycaches/export_test.go b/pkg/component/registrycaches/export_test.go new file mode 100644 index 00000000..0855a9c3 --- /dev/null +++ b/pkg/component/registrycaches/export_test.go @@ -0,0 +1,17 @@ +// Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// 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 registrycaches + +var ComputeName = computeName diff --git a/pkg/component/registrycaches/registry_caches.go b/pkg/component/registrycaches/registry_caches.go index 97806369..7ab74e8a 100644 --- a/pkg/component/registrycaches/registry_caches.go +++ b/pkg/component/registrycaches/registry_caches.go @@ -276,7 +276,7 @@ func (r *registryCaches) computeResourcesDataForRegistryCache(ctx context.Contex ) var ( - name = strings.Replace(fmt.Sprintf("registry-%s", cache.Upstream), ".", "-", -1) + name = computeName(cache.Upstream) configValues = map[string]interface{}{ "http_addr": fmt.Sprintf(":%d", constants.RegistryCachePort), "http_debug_addr": fmt.Sprintf(":%d", debugPort), @@ -513,3 +513,26 @@ func getLabels(name, upstream string) map[string]string { constants.UpstreamHostLabel: upstream, } } + +// computeName computes a name by given upstream. +// The name later on is used by the registry cache Service, config Secret, StatefulSet and VPA. +// +// If length of registry- is NOT > 52, the name is registry-. +// Otherwise it is registry-- where is truncated at 37 chars. +// The returned name is at most 52 chars. +func computeName(upstream string) string { + // The StatefulSet name limit is 63 chars. However Pods for a StatefulSet with name > 52 chars cannot be created due to https://github.com/kubernetes/kubernetes/issues/64023. + // The "controller-revision-hash" label gets added to the StatefulSet Pod. The label value is in format _ where is 10 or 11 chars. + // A label value limit is 63 chars. That's why a Pod for a StatefulSet with name > 52 chars cannot be created. + const statefulSetNameLimit = 52 + + escapedUpstream := strings.Replace(upstream, ".", "-", -1) + name := "registry-" + escapedUpstream + if len(name) > statefulSetNameLimit { + hash := utils.ComputeSHA256Hex([]byte(upstream))[:5] + upstreamLimit := statefulSetNameLimit - len("registry-") - len(hash) - 1 + name = fmt.Sprintf("registry-%s-%s", escapedUpstream[:upstreamLimit], hash) + } + + return name +} diff --git a/pkg/component/registrycaches/registry_caches_test.go b/pkg/component/registrycaches/registry_caches_test.go index fe3e1b4d..ac03ed20 100644 --- a/pkg/component/registrycaches/registry_caches_test.go +++ b/pkg/component/registrycaches/registry_caches_test.go @@ -707,6 +707,17 @@ metadata: }) }) }) + + DescribeTable("#computeName", + func(upstream, expected string) { + actual := ComputeName(upstream) + Expect(len(actual)).NotTo(BeNumerically(">", 52)) + Expect(actual).To(Equal(expected)) + }, + + Entry("short upstream", "docker.io", "registry-docker-io"), + Entry("long upstream", "myproj-releases.common.repositories.cloud.com", "registry-myproj-releases-common-repositories-c-3f834"), + ) }) func encodeBase64(val string) string {