diff --git a/Dockerfile b/Dockerfile index a7a088ad0be..519beae4c30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ ENV CROMWELL_CHART_VERSION 0.2.506 ENV HAIL_BATCH_CHART_VERSION 0.2.0 ENV RSTUDIO_CHART_VERSION 0.11.0 ENV SAS_CHART_VERSION 0.14.0 +ENV OFFICE_SUITE_CHART_VERSION 0.1.0 RUN mkdir /leonardo COPY ./leonardo*.jar /leonardo @@ -67,6 +68,7 @@ RUN cd /leonardo && \ helm pull cromwell-helm/cromwell --version $CROMWELL_CHART_VERSION --untar && \ helm pull terra-helm/rstudio --version $RSTUDIO_CHART_VERSION --untar && \ helm pull terra-helm/sas --version $SAS_CHART_VERSION --untar && \ + helm pull terra-helm/officesuite --version $OFFICE_SUITE_CHART_VERSION --untar && \ helm pull oci://terradevacrpublic.azurecr.io/hail/hail-batch-terra-azure --version $HAIL_BATCH_CHART_VERSION --untar && \ cd / diff --git a/core/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModels.scala b/core/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModels.scala index 0d7213473b8..72a0ff37c36 100644 --- a/core/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModels.scala +++ b/core/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModels.scala @@ -323,10 +323,15 @@ object AllowedChartName { def asString: String = "sas" } + final case object Officesuite extends AllowedChartName { + def asString: String = "Officesuite" + } + // We used to have different chart names for RStudio and SAS. This is to handle the old names for backwards-compatibility private val deprecatedName: Map[String, AllowedChartName] = Map( "aou-rstudio-chart" -> RStudio, - "aou-sas-chart" -> Sas + "aou-sas-chart" -> Sas, + "aou-officesuite-chart" -> Officesuite ) def stringToObject: Map[String, AllowedChartName] = diff --git a/core/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModelsSpec.scala b/core/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModelsSpec.scala index c398403b0e4..0dcd544f236 100644 --- a/core/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModelsSpec.scala +++ b/core/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/kubernetesModelsSpec.scala @@ -8,6 +8,7 @@ class kubernetesModelsSpec extends LeonardoTestSuite with Matchers with AnyFlatS it should "convert chartName to AllowedChartName correctly" in { AllowedChartName.fromChartName(ChartName("/leonardo/cromwell")) shouldBe None AllowedChartName.fromChartName(ChartName("/leonardo/sas")) shouldBe Some(AllowedChartName.Sas) + AllowedChartName.fromChartName(ChartName("/leonardo/officesuite")) shouldBe Some(AllowedChartName.Officesuite) AllowedChartName.fromChartName(ChartName("/leonardo/rstudio")) shouldBe Some( AllowedChartName.RStudio ) diff --git a/http/src/main/resources/reference.conf b/http/src/main/resources/reference.conf index e4dd5cde7aa..bcfa47d205a 100644 --- a/http/src/main/resources/reference.conf +++ b/http/src/main/resources/reference.conf @@ -845,6 +845,7 @@ gke { chartName = "/leonardo/" rstudioChartVersion = "0.11.0" sasChartVersion = "0.14.0" + officeSuiteChartVersion = "0.1.0" services = [ { diff --git a/http/src/main/resources/swagger/api-docs.yaml b/http/src/main/resources/swagger/api-docs.yaml index aaa6ea003fe..bb572cfc275 100644 --- a/http/src/main/resources/swagger/api-docs.yaml +++ b/http/src/main/resources/swagger/api-docs.yaml @@ -2993,6 +2993,7 @@ components: enum: - rstudio - sas + - officesuite AppStatus: type: string enum: diff --git a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/Config.scala b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/Config.scala index 1f46a76e6df..bf6b9306aa4 100644 --- a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/Config.scala +++ b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/Config.scala @@ -730,6 +730,7 @@ object Config { config.as[ChartName]("chartName"), config.as[ChartVersion]("rstudioChartVersion"), config.as[ChartVersion]("sasChartVersion"), + config.as[ChartVersion]("officeSuiteChartVersion"), config.as[NamespaceNameSuffix]("namespaceNameSuffix"), config.as[ReleaseNameSuffix]("releaseNameSuffix"), config.as[List[ServiceConfig]]("services"), diff --git a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/KubernetesAppConfig.scala b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/KubernetesAppConfig.scala index 99295690bb1..9fc5be75dd2 100644 --- a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/KubernetesAppConfig.scala +++ b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/config/KubernetesAppConfig.scala @@ -206,6 +206,7 @@ final case class ContainerRegistryCredentials(username: ContainerRegistryUsernam final case class AllowedAppConfig(chartName: ChartName, rstudioChartVersion: ChartVersion, sasChartVersion: ChartVersion, + officeSuiteChartVersion: ChartVersion, namespaceNameSuffix: NamespaceNameSuffix, releaseNameSuffix: ReleaseNameSuffix, services: List[ServiceConfig], diff --git a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/http/service/LeoAppServiceInterp.scala b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/http/service/LeoAppServiceInterp.scala index 3b46f5362d8..ffaaa5801e1 100644 --- a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/http/service/LeoAppServiceInterp.scala +++ b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/http/service/LeoAppServiceInterp.scala @@ -106,6 +106,7 @@ final class LeoAppServiceInterp[F[_]: Parallel](config: AppServiceConfig, case Some(cn) => cn match { case AllowedChartName.RStudio => F.unit + case AllowedChartName.Officesuite => F.unit case AllowedChartName.Sas => if (config.enableSasApp) { if (enableIntraNodeVisibility) { @@ -1464,6 +1465,7 @@ final class LeoAppServiceInterp[F[_]: Parallel](config: AppServiceConfig, val chartVersion = req.allowedChartName.get match { case AllowedChartName.RStudio => config.leoKubernetesConfig.allowedAppConfig.rstudioChartVersion case AllowedChartName.Sas => config.leoKubernetesConfig.allowedAppConfig.sasChartVersion + case AllowedChartName.Officesuite => config.leoKubernetesConfig.allowedAppConfig.officeSuiteChartVersion } gkeAppConfig.chart .lens(_.name) diff --git a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/monitor/LeoPubsubMessageSubscriber.scala b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/monitor/LeoPubsubMessageSubscriber.scala index bb828c7ac74..ea0e71636aa 100644 --- a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/monitor/LeoPubsubMessageSubscriber.scala +++ b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/monitor/LeoPubsubMessageSubscriber.scala @@ -1505,7 +1505,7 @@ class LeoPubsubMessageSubscriber[F[_]]( latestAppChartVersion <- KubernetesAppConfig.configForTypeAndCloud(appResult.app.appType, msg.cloudContext.cloudProvider ) match { - case Some(AllowedAppConfig(_, rstudioChartVersion, sasChartVersion, _, _, _, _, _, _, _)) => + case Some(AllowedAppConfig(_, rstudioChartVersion, sasChartVersion, officesuiteChartVersion, _, _, _, _, _, _, _)) => AllowedChartName.fromChartName(appResult.app.chart.name) match { case Some(AllowedChartName.RStudio) => F.pure(rstudioChartVersion) diff --git a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValues.scala b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValues.scala index 3fcf3723e1f..ca488b4a918 100644 --- a/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValues.scala +++ b/http/src/main/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValues.scala @@ -342,6 +342,17 @@ private[leonardo] object BuildHelmChartValues { raw"""imageCredentials.username=${config.allowedAppConfig.sasContainerRegistryCredentials.username.asString}""", raw"""imageCredentials.password=${config.allowedAppConfig.sasContainerRegistryCredentials.password.asString}""" ) ++ common + + case AllowedChartName.Officesuite => + List( + raw"""ingress.officesuite.path=${ingressPath}${"(/|$)(.*)"}""", + raw"""ingress.welder.path=${welderIngressPath}${"(/|$)(.*)"}""", + raw"""ingress.annotations.nginx\.ingress\.kubernetes\.io/proxy-redirect-from=https://${ + k8sProxyHost + .address() + }""", + raw"""proxySubpath=${ingressPath.drop(1)}""", + ) ++ common } } diff --git a/http/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValuesSpec.scala b/http/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValuesSpec.scala index 81cd5e18daa..de4213596ef 100644 --- a/http/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValuesSpec.scala +++ b/http/src/test/scala/org/broadinstitute/dsde/workbench/leonardo/util/BuildHelmChartValuesSpec.scala @@ -394,6 +394,63 @@ class BuildHelmChartValuesSpec extends AnyFlatSpecLike with LeonardoTestSuite { """gcsfuse.enabled=false""" } + it should "build OfficeSuite override values string" in { + val savedCluster1 = makeKubeCluster(1) + val savedDisk1 = makePersistentDisk(Some(DiskName("disk1"))) + val envVariables = Map("WORKSPACE_NAME" -> "test-workspace-name") + val res = buildAllowedAppChartOverrideValuesString( + Config.gkeInterpConfig, + AllowedChartName.Officesuite, + appName = AppName("app1"), + cluster = savedCluster1, + nodepoolName = Some(NodepoolName("pool1")), + namespaceName = NamespaceName("ns"), + disk = savedDisk1, + ksaName = ServiceAccountName("app1-officesuite-ksa"), + userEmail = userEmail2, + stagingBucket = GcsBucketName("test-staging-bucket"), + envVariables, + None, + Some(GcsBucketName("fc-bucket")) + ) + + res.mkString(",") shouldBe + """ingress.officesuite.path=/proxy/google/v1/apps/dsp-leo-test1/app1/app(/|$)(.*),""" + + """ingress.welder.path=/proxy/google/v1/apps/dsp-leo-test1/app1/welder-service(/|$)(.*),""" + + """ingress.annotations.nginx\.ingress\.kubernetes\.io/proxy-redirect-from=https://1455694897.jupyter.firecloud.org,""" + + """fullnameOverride=app1,""" + + """persistence.size=250G,""" + + """persistence.gcePersistentDisk=disk1,""" + + """serviceAccount.name=app1-officesuite-ksa,""" + + """ingress.enabled=true,""" + + """ingress.annotations.nginx\.ingress\.kubernetes\.io/auth-tls-secret=ns/ca-secret,""" + + """ingress.annotations.nginx\.ingress\.kubernetes\.io/proxy-redirect-to=https://leo/proxy/google/v1/apps/dsp-leo-test1/app1/app,""" + + """ingress.annotations.nginx\.ingress\.kubernetes\.io/rewrite-target=/$2,""" + + """ingress.annotations.nginx\.ingress\.kubernetes\.io/proxy-cookie-path=/ "/; Secure; SameSite=None; HttpOnly",""" + + """ingress.host=1455694897.jupyter.firecloud.org,""" + + """ingress.tls[0].secretName=tls-secret,""" + + """ingress.tls[0].hosts[0]=1455694897.jupyter.firecloud.org,""" + + """welder.extraEnv[0].name=GOOGLE_PROJECT,""" + + """welder.extraEnv[0].value=dsp-leo-test1,""" + + """welder.extraEnv[1].name=STAGING_BUCKET,""" + + """welder.extraEnv[1].value=test-staging-bucket,""" + + """welder.extraEnv[2].name=CLUSTER_NAME,""" + + """welder.extraEnv[2].value=app1,""" + + """welder.extraEnv[3].name=OWNER_EMAIL,""" + + """welder.extraEnv[3].value=user2@example.com,""" + + """welder.extraEnv[4].name=WORKSPACE_ID,""" + + """welder.extraEnv[4].value=dummy,""" + + """welder.extraEnv[5].name=WSM_URL,""" + + """welder.extraEnv[5].value=dummy,""" + + """extraEnv[0].name=WORKSPACE_NAME,""" + + """extraEnv[0].value=test-workspace-name,""" + + """replicaCount=1,""" + + """nodeSelector.cloud\.google\.com/gke-nodepool=pool1,""" + + """gcsfuse.enabled=true,""" + + """gcsfuse.bucket=fc-bucket""" + """proxySubpath=proxy/google/v1/apps/dsp-leo-test1/app1/app""" + } + it should "build SAS override values string in autopilot mode" in { val savedCluster1 = makeKubeCluster(1) val savedDisk1 = makePersistentDisk(Some(DiskName("disk1")))