diff --git a/stx-init-env b/stx-init-env index a43c3120c..edf66cfb4 100755 --- a/stx-init-env +++ b/stx-init-env @@ -83,6 +83,7 @@ START_PODS=1 RESET_SOFT=0 RESET_HARD=0 ASSUME_YES=0 +STX_START_OPTS= COREUTILS_DOCKER_IMAGE="debian:bookworm-20240130-slim" @@ -238,7 +239,7 @@ stx_stop() { stx_start() { stx config --upgrade || exit 1 - stx control start --wait || exit 1 + stx control start --wait $STX_START_OPTS || exit 1 } # @@ -710,6 +711,10 @@ elif [[ $RESTART_MINIKUBE -eq 1 ]] ; then warn "--restart-minikube is only supported on minikube platform -- ignoring" fi +if [[ "$DOCKERHUB_LOGIN" -eq 1 ]] ; then + STX_START_OPTS+=" --use-dockerhub-cred" +fi + # Workaround: Wait for Minikube network to stabilize before building images sleep 10 diff --git a/stx/lib/stx/k8s.py b/stx/lib/stx/k8s.py index 61de5f65d..82c3e025f 100644 --- a/stx/lib/stx/k8s.py +++ b/stx/lib/stx/k8s.py @@ -13,7 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # +import json import logging +import os +import re from stx import utils # pylint: disable=E0611 import subprocess import tempfile @@ -115,6 +118,87 @@ class KubeHelper(object): return podname + def __get_docker_cred_secret_name(self): + project_name = re.sub(r'[^a-z0-9-]', r'-', + self.config.get('project', 'name').lower()) + return project_name + '-dockerconfigjson' + + def try_create_docker_cred_secret(self): + '''Create a k8s secret with Docker Hub credentials. + + Check the file $HOME/.docker/config.json for Docker Hub + credentials. If if found, create the secret and return + its name. Otherwise, do nothing and return None. + ''' + + cred_name = self.__get_docker_cred_secret_name() + + # Create a temporary docker config file that contains only the + # docker hub credentials, by extracting it from the calling user's + # docker config + + # Find docker config location + docker_config = '%s/config.json' % \ + os.getenv('DOCKER_CONFIG', + os.path.expanduser('~/.docker')) + try: + with open(docker_config) as f: + docker_config_data = json.load(f) + except FileNotFoundError: + return None + + # Look for dockerhub credentials + dockerhub_auth = docker_config_data.get('auths', {})\ + .get('https://index.docker.io/v1/', {})\ + .get('auth') + if not dockerhub_auth: + return None + + # Create a temporary file that contains only docker hub credentials + with tempfile.NamedTemporaryFile(mode='w+t', + encoding='utf8', + prefix='stx_docker_config_', + suffix='.json') as f: + new_docker_config_data = { + 'auths': { + 'https://index.docker.io/v1/': { + 'auth': dockerhub_auth + } + } + } + json.dump(new_docker_config_data, f) + f.flush() + + # (re-)create the secret + self.__delete_docker_cred_secret(cred_name) + create_cmd = self.config.kubectl() + f' create secret generic {cred_name}' + \ + f' --from-file=.dockerconfigjson="{f.name}"' + \ + ' --type=kubernetes.io/dockerconfigjson' + logger.info('Running: %s', create_cmd) + subprocess.run(create_cmd, shell=True, check=True) + + return cred_name + + def delete_docker_cred_secret(self): + '''Delete the docker secret from k8s + + Do nothing if it doesn't exist. + ''' + self.__delete_docker_cred_secret(self.__get_docker_cred_secret_name()) + + def __delete_docker_cred_secret(self, cred_name): + delete_cmd = self.config.kubectl() + \ + f' delete secret {cred_name} --ignore-not-found' + try: + logger.info('Running: %s', delete_cmd) + subprocess.run(delete_cmd, shell=True, + stderr=subprocess.PIPE, check=True, + encoding='utf8', errors='utf8') + except subprocess.CalledProcessError as x: + logger.error('Failed while attempting to delete k8s ' + + 'credentials "%s": %s', cred_name, x.stderr) + raise x + def helm_release_exists(self, projectname): '''Check if the helm release exists''' diff --git a/stx/lib/stx/stx_control.py b/stx/lib/stx/stx_control.py index b41cc2585..7f0b1a7c1 100644 --- a/stx/lib/stx/stx_control.py +++ b/stx/lib/stx/stx_control.py @@ -251,7 +251,7 @@ stx-pkgbuilder/configmap/') return repomgr_type - def handleStartTask(self, projectname, wait): + def handleStartTask(self, projectname, wait, use_dockerhub_cred): if self.config.use_minikube: self.minikube_ctl.start() @@ -271,6 +271,11 @@ stx-pkgbuilder/configmap/') if self.config.container_mtu: cmd += f' --set stx-docker.mtu={self.config.container_mtu}' + if use_dockerhub_cred: + image_pull_secret = self.k8s.try_create_docker_cred_secret() + if image_pull_secret: + cmd += f' --set global.imagePullSecrets[0].name={image_pull_secret}' + self.logger.debug('Execute the helm start command: %s', cmd) helm_status = self.k8s.helm_release_exists(self.projectname) if helm_status: @@ -317,6 +322,8 @@ stx-pkgbuilder/configmap/') self.logger.info("waiting for %d pod(s) to exit", pod_count) time.sleep(2) + self.k8s.delete_docker_cred_secret() + def handleIsStartedTask(self, projectname): if self.k8s.helm_release_exists(projectname): self.logger.info('Helm release %s is installed' % projectname) @@ -420,7 +427,8 @@ no lat container is available!') projectname = 'stx' if args.ctl_task == 'start': - self.handleStartTask(projectname, args.wait) + self.handleStartTask(projectname, args.wait, + args.use_dockerhub_cred) elif args.ctl_task == 'stop': self.handleStopTask(projectname, args.wait) diff --git a/stx/lib/stx/stx_main.py b/stx/lib/stx/stx_main.py index 2cba4fce2..d40d280b3 100644 --- a/stx/lib/stx/stx_main.py +++ b/stx/lib/stx/stx_main.py @@ -84,6 +84,12 @@ task.\t\teg: [start|enter|stop|is-started|status|upgrade|keys-add]') help='wait for operation to finish, ' + 'for start, stop\n\n', action='store_true') + control_subparser.add_argument('--use-dockerhub-cred', + help='Use dockerhub credentials from ' + + '$HOME/.docker/config for pulling ' + + 'environment pods\' images within ' + + 'k8s (for "start" command only)\n\n', + action='store_true') control_subparser.set_defaults(handle=self.handlecontrol.handleControl) config_subparser = subparsers.add_parser('config', diff --git a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-aptly/stx-repomgr/templates/deployment.yaml b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-aptly/stx-repomgr/templates/deployment.yaml index 290db2f10..7fa4f3afe 100644 --- a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-aptly/stx-repomgr/templates/deployment.yaml +++ b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-aptly/stx-repomgr/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: labels: {{- include "stx-repomgr.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with (.Values.imagePullSecrets | default .Values.global.imagePullSecrets) }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-builder-files-http/templates/deployment.yaml b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-builder-files-http/templates/deployment.yaml index 88f1dff5f..d606e2e38 100644 --- a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-builder-files-http/templates/deployment.yaml +++ b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-builder-files-http/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: labels: {{- include "stx-builder-files-http.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with (.Values.imagePullSecrets | default .Values.global.imagePullSecrets) }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-docker/templates/deployment.yaml b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-docker/templates/deployment.yaml index bf9f9bfe7..b38650aed 100644 --- a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-docker/templates/deployment.yaml +++ b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-docker/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: labels: {{- include "stx-docker.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with (.Values.imagePullSecrets | default .Values.global.imagePullSecrets) }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-lat-tool/templates/deployment.yaml b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-lat-tool/templates/deployment.yaml index a3c134197..4a13aaf97 100644 --- a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-lat-tool/templates/deployment.yaml +++ b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-lat-tool/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: labels: {{- include "stx-lat-tool.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with (.Values.imagePullSecrets | default .Values.global.imagePullSecrets) }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pkgbuilder/templates/deployment.yaml b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pkgbuilder/templates/deployment.yaml index 5052127e3..1d0bb2fd6 100644 --- a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pkgbuilder/templates/deployment.yaml +++ b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pkgbuilder/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: labels: {{- include "stx-pkgbuilder.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with (.Values.imagePullSecrets | default .Values.global.imagePullSecrets) }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pulp/stx-repomgr/templates/deployment.yaml b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pulp/stx-repomgr/templates/deployment.yaml index b991738de..9a98680fe 100644 --- a/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pulp/stx-repomgr/templates/deployment.yaml +++ b/stx/stx-build-tools-chart/stx-builder/dependency_chart/stx-pulp/stx-repomgr/templates/deployment.yaml @@ -21,7 +21,7 @@ spec: labels: {{- include "stx-repomgr.selectorLabels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with (.Values.imagePullSecrets | default .Values.global.imagePullSecrets) }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }}