diff --git a/deployment/helm/skaha/skaha-config/launch-carta.yaml b/deployment/helm/skaha/skaha-config/launch-carta.yaml index 065fae8a..b2b11a4e 100644 --- a/deployment/helm/skaha/skaha-config/launch-carta.yaml +++ b/deployment/helm/skaha/skaha-config/launch-carta.yaml @@ -28,6 +28,8 @@ spec: enableServiceLinks: false restartPolicy: OnFailure ${skaha.schedulegpu} + imagePullSecrets: + - name: ${software.imagesecret} securityContext: {{ template "skaha.job.securityContext" . }} priorityClassName: uber-user-preempt-medium diff --git a/skaha/src/main/java/org/opencadc/skaha/SkahaAction.java b/skaha/src/main/java/org/opencadc/skaha/SkahaAction.java index 32aaac48..33974637 100644 --- a/skaha/src/main/java/org/opencadc/skaha/SkahaAction.java +++ b/skaha/src/main/java/org/opencadc/skaha/SkahaAction.java @@ -398,7 +398,7 @@ protected int getUID() { return posixPrincipal.getUidNumber(); } - public Image getImage(String imageID) throws Exception { + public Image getImage(String imageID) { log.debug("get image: " + imageID); List images = redis.getAll("public", Image.class); if (images == null) { diff --git a/skaha/src/main/java/org/opencadc/skaha/session/PostAction.java b/skaha/src/main/java/org/opencadc/skaha/session/PostAction.java index 010339a0..2c9fefd5 100644 --- a/skaha/src/main/java/org/opencadc/skaha/session/PostAction.java +++ b/skaha/src/main/java/org/opencadc/skaha/session/PostAction.java @@ -97,6 +97,7 @@ import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; +import org.opencadc.skaha.utils.CommandExecutioner; import org.opencadc.skaha.utils.PosixCache; import static org.opencadc.skaha.utils.CommandExecutioner.execute; @@ -141,12 +142,13 @@ public class PostAction extends SessionAction { public static final String HEADLESS_PRIORITY = "headless.priority"; public static final String HEADLESS_IMAGE_BUNDLE = "headless.image.bundle"; private static final String CREATE_USER_BASE_COMMAND = "/usr/local/bin/add-user"; - private static final String DEFAULT_HARBOR_SECRET = "notused"; private static final String DESKTOP_SESSION_APP_TOKEN = "software.desktop.app.token"; private static final String POSIX_MAPPER_URI = "POSIX_MAPPER_URI"; private static final String REGISTRY_URL = "REGISTRY_URL"; private static final String SKAHA_TLD = "SKAHA_TLD"; + public static final String DEFAULT_SOFTWARE_IMAGESECRET_VALUE = "notused"; + public PostAction() { super(); } @@ -618,6 +620,8 @@ public void createSession(String type, String image, String name, Integer cores, new LocalAuthority().getServiceURI(RegistryClient.class.getName() + ".baseURL").toString()); jobLaunchString = setConfigValue(jobLaunchString, SKAHA_TLD, skahaTld); + jobLaunchString = setConfigValue(jobLaunchString, PostAction.SOFTWARE_IMAGESECRET, createRegistryImageSecret(image)); + if (type.equals(SessionAction.SESSION_TYPE_DESKTOP)) { jobLaunchString = setConfigValue(jobLaunchString, PostAction.DESKTOP_SESSION_APP_TOKEN, generateToken()); } @@ -665,6 +669,31 @@ private String generateToken() throws Exception { return SkahaAction.getTokenTool().generateToken(URI.create(this.skahaUsersGroup), WriteGrant.class, this.sessionID); } + /** + * Create a registry secret and return its name. + * @param imageID The image ID to create a secret for. + * @return String secret name, never null. + */ + private String createRegistryImageSecret(final String imageID) { + final String registryAuth = getRegistryAuth(); + final String username = this.posixPrincipal.username; + final String secretName = "harbor-secret-" + username.toLowerCase(); + CommandExecutioner.ensureRegistrySecret(getRegistryHost(imageID), username, + StringUtil.hasText(registryAuth) ? registryAuth : PostAction.DEFAULT_SOFTWARE_IMAGESECRET_VALUE, + secretName); + + return secretName; + } + + private String getRegistryHost(final String imageID) { + final String registryHost = this.harborHosts.stream().filter(imageID::startsWith).findFirst().orElse(null); + if (registryHost == null) { + throw new IllegalArgumentException("not a skaha harbor image: " + imageID); + } + + return registryHost; + } + /** * Attach a desktop application. * TODO: This method requires rework. The Job Name does not use the same mechanism as the K8SUtil.getJobName() diff --git a/skaha/src/main/java/org/opencadc/skaha/utils/CommandExecutioner.java b/skaha/src/main/java/org/opencadc/skaha/utils/CommandExecutioner.java index e712df78..42848c9f 100644 --- a/skaha/src/main/java/org/opencadc/skaha/utils/CommandExecutioner.java +++ b/skaha/src/main/java/org/opencadc/skaha/utils/CommandExecutioner.java @@ -81,7 +81,7 @@ public static void execute(final String[] command, final OutputStream standardOu } } - protected static void ensureRegistrySecret(final String registryHost, final String registryUsername, final String secret, final String secretName) { + public static void ensureRegistrySecret(final String registryHost, final String registryUsername, final String secret, final String secretName) { // create new secret String[] createCmd = new String[] { "kubectl", "--namespace", K8SUtil.getWorkloadNamespace(), "create", "secret", "docker-registry",