Skip to content

Commit 30c83f1

Browse files
committed
Refine parameter handling in Runner and Solution services
- Added new MIME types for solution file uploads. - Enhanced `RunnerService` to validate and filter run template parameters during creation and updates. - Updated `RunnerDatasets` and related integration tests to reflect the new MIME type and parameter handling logic. - Adjusted error messages for missing run templates in `RunnerApiService`.
1 parent 8be7f8b commit 30c83f1

File tree

4 files changed

+131
-27
lines changed

4 files changed

+131
-27
lines changed

api/src/integrationTest/kotlin/com/cosmotech/api/home/runner/RunnerControllerTests.kt

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,25 @@ import com.cosmotech.api.home.runner.RunnerConstants.RUNNER_RUN_TEMPLATE
2828
import com.cosmotech.api.rbac.ROLE_ADMIN
2929
import com.cosmotech.api.rbac.ROLE_NONE
3030
import com.cosmotech.api.rbac.ROLE_VIEWER
31+
import com.cosmotech.dataset.domain.DatasetPartTypeEnum
3132
import com.cosmotech.runner.domain.*
3233
import com.cosmotech.runner.domain.ResourceSizeInfo
34+
import com.cosmotech.runner.service.DATASET_PART_VARTYPE_FILE
3335
import com.cosmotech.solution.domain.RunTemplateCreateRequest
36+
import com.cosmotech.solution.domain.RunTemplateParameterCreateRequest
37+
import com.cosmotech.solution.domain.RunTemplateParameterGroupCreateRequest
3438
import com.cosmotech.solution.domain.RunTemplateResourceSizing
3539
import com.ninjasquad.springmockk.SpykBean
3640
import io.mockk.every
41+
import org.apache.commons.io.IOUtils
3742
import org.json.JSONObject
3843
import org.junit.jupiter.api.BeforeEach
3944
import org.junit.jupiter.api.Test
4045
import org.slf4j.LoggerFactory
4146
import org.springframework.beans.factory.annotation.Autowired
4247
import org.springframework.boot.test.context.SpringBootTest
4348
import org.springframework.http.MediaType
49+
import org.springframework.mock.web.MockMultipartFile
4450
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document
4551
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
4652
import org.springframework.test.context.ActiveProfiles
@@ -61,6 +67,12 @@ class RunnerControllerTests : ControllerTestBase() {
6167

6268
@SpykBean @Autowired private lateinit var eventPublisher: CsmEventPublisher
6369

70+
private val solutionParameterId1 = "param1"
71+
private val solutionParameterDefaultValue1 = "this_is_a_default_value"
72+
private val solutionParameterVarType1 = "string"
73+
private val solutionParameterId2 = "param2"
74+
private val solutionParameterDefaultValue2 = "my_folder_test/test.txt"
75+
6476
@BeforeEach
6577
fun beforeEach() {
6678

@@ -74,6 +86,25 @@ class RunnerControllerTests : ControllerTestBase() {
7486
RunTemplateResourceSizing(
7587
com.cosmotech.solution.domain.ResourceSizeInfo("cpu_requests", "memory_requests"),
7688
com.cosmotech.solution.domain.ResourceSizeInfo("cpu_limits", "memory_limits"))
89+
90+
val parametersList =
91+
mutableListOf(
92+
RunTemplateParameterCreateRequest(
93+
id = solutionParameterId1,
94+
varType = solutionParameterVarType1,
95+
defaultValue = solutionParameterDefaultValue1,
96+
),
97+
RunTemplateParameterCreateRequest(
98+
id = solutionParameterId2,
99+
varType = DATASET_PART_VARTYPE_FILE,
100+
defaultValue = solutionParameterDefaultValue2,
101+
))
102+
103+
val parameterGroups =
104+
mutableListOf(
105+
RunTemplateParameterGroupCreateRequest(
106+
id = parameterGroupId,
107+
parameters = mutableListOf(solutionParameterId1, solutionParameterId2)))
77108
val runTemplates =
78109
mutableListOf(
79110
RunTemplateCreateRequest(
@@ -90,12 +121,36 @@ class RunnerControllerTests : ControllerTestBase() {
90121
organizationId = createOrganizationAndReturnId(mvc, constructOrganizationCreateRequest())
91122
solutionId =
92123
createSolutionAndReturnId(
93-
mvc, organizationId, constructSolutionCreateRequest(runTemplates = runTemplates))
124+
mvc,
125+
organizationId,
126+
constructSolutionCreateRequest(
127+
parameters = parametersList,
128+
parameterGroups = parameterGroups,
129+
runTemplates = runTemplates))
94130
workspaceId =
95131
createWorkspaceAndReturnId(
96132
mvc, organizationId, constructWorkspaceCreateRequest(solutionId = solutionId))
97133
datasetId =
98134
createDatasetAndReturnId(mvc, organizationId, workspaceId, constructDatasetCreateRequest())
135+
136+
val fileName = "test.txt"
137+
val fileToUpload =
138+
this::class.java.getResourceAsStream("/solution/$fileName")
139+
?: throw IllegalStateException(
140+
"$fileName file used for organizations/{organization_id}/solutions/{solution_id}/files/POST endpoint documentation cannot be null")
141+
142+
val mockFile =
143+
MockMultipartFile(
144+
"file", fileName, MediaType.TEXT_PLAIN_VALUE, IOUtils.toByteArray(fileToUpload))
145+
146+
mvc.perform(
147+
multipart("/organizations/$organizationId/solutions/$solutionId/files")
148+
.file(mockFile)
149+
.param("overwrite", "true")
150+
.param("destination", "my_folder_test/test.txt")
151+
.accept(MediaType.APPLICATION_JSON)
152+
.with(csrf()))
153+
.andExpect(status().is2xxSuccessful)
99154
}
100155

101156
@Test
@@ -107,9 +162,7 @@ class RunnerControllerTests : ControllerTestBase() {
107162
val description = "this_is_a_description"
108163
val tags = mutableListOf("tags1", "tags2")
109164
val datasetList = mutableListOf(datasetId)
110-
val runnerParameterId = "parameterId1"
111165
val runnerParameterValue = "parameter_value"
112-
val runnerParameterVarType = "this_is_a_vartype"
113166

114167
val parentId =
115168
createRunnerAndReturnId(
@@ -150,9 +203,9 @@ class RunnerControllerTests : ControllerTestBase() {
150203
parametersValues =
151204
mutableListOf(
152205
RunnerRunTemplateParameterValue(
153-
parameterId = runnerParameterId,
206+
parameterId = solutionParameterId1,
154207
value = runnerParameterValue,
155-
varType = runnerParameterVarType,
208+
varType = solutionParameterVarType1,
156209
isInherited = false)))
157210

158211
mvc.perform(
@@ -177,9 +230,9 @@ class RunnerControllerTests : ControllerTestBase() {
177230
.andExpect(jsonPath("$.runSizing.requests.memory").value("memory_requests"))
178231
.andExpect(jsonPath("$.runSizing.limits.cpu").value("cpu_limits"))
179232
.andExpect(jsonPath("$.runSizing.limits.memory").value("memory_limits"))
180-
.andExpect(jsonPath("$.parametersValues[0].parameterId").value(runnerParameterId))
233+
.andExpect(jsonPath("$.parametersValues[0].parameterId").value(solutionParameterId1))
181234
.andExpect(jsonPath("$.parametersValues[0].value").value(runnerParameterValue))
182-
.andExpect(jsonPath("$.parametersValues[0].varType").value(runnerParameterVarType))
235+
.andExpect(jsonPath("$.parametersValues[0].varType").value(solutionParameterVarType1))
183236
.andExpect(jsonPath("$.parametersValues[0].isInherited").value(false))
184237
.andExpect(jsonPath("$.security.accessControlList[0].role").value(NEW_USER_ROLE))
185238
.andExpect(jsonPath("$.security.accessControlList[0].id").value(NEW_USER_ID))
@@ -264,16 +317,21 @@ class RunnerControllerTests : ControllerTestBase() {
264317
.andExpect(jsonPath("$.solutionName").value(solutionName))
265318
.andExpect(jsonPath("$.runTemplateName").value(runTemplateName))
266319
.andExpect(jsonPath("$.tags").value(tags))
267-
.andExpect(jsonPath("$.datasetList").value(datasetList))
320+
.andExpect(jsonPath("$.datasets.bases").value(datasetList))
321+
.andExpect(jsonPath("$.datasets.parameters[0].name").value(solutionParameterId2))
322+
.andExpect(jsonPath("$.datasets.parameters[0].type").value(DatasetPartTypeEnum.File.name))
323+
.andExpect(
324+
jsonPath("$.datasets.parameters[0].sourceName")
325+
.value(solutionParameterDefaultValue2.substringAfterLast("/")))
268326
.andExpect(jsonPath("$.security.default").value(ROLE_NONE))
269327
.andExpect(jsonPath("$.runSizing.requests.cpu").value("cpu_requests"))
270328
.andExpect(jsonPath("$.runSizing.requests.memory").value("memory_requests"))
271329
.andExpect(jsonPath("$.runSizing.limits.cpu").value("cpu_limits"))
272330
.andExpect(jsonPath("$.runSizing.limits.memory").value("memory_limits"))
273-
.andExpect(jsonPath("$.parametersValues[0].parameterId").value(runnerParameterId))
274-
.andExpect(jsonPath("$.parametersValues[0].value").value(runnerParameterValue))
275-
.andExpect(jsonPath("$.parametersValues[0].varType").value(runnerParameterVarType))
276-
.andExpect(jsonPath("$.parametersValues[0].isInherited").value(false))
331+
.andExpect(jsonPath("$.parametersValues[0].parameterId").value(solutionParameterId1))
332+
.andExpect(jsonPath("$.parametersValues[0].value").value(solutionParameterDefaultValue1))
333+
.andExpect(jsonPath("$.parametersValues[0].varType").value(solutionParameterVarType1))
334+
.andExpect(jsonPath("$.parametersValues[0].isInherited").value(true))
277335
.andExpect(jsonPath("$.security.accessControlList[0].role").value(NEW_USER_ROLE))
278336
.andExpect(jsonPath("$.security.accessControlList[0].id").value(NEW_USER_ID))
279337
.andDo(MockMvcResultHandlers.print())
@@ -291,7 +349,6 @@ class RunnerControllerTests : ControllerTestBase() {
291349
val description = "this_is_a_description"
292350
val tags = mutableListOf("tags1", "tags2")
293351
val datasetList = mutableListOf(datasetId)
294-
val runnerParameterId = "parameterId1"
295352
val runnerParameterValue = "parameter_value"
296353
val runnerParameterVarType = "this_is_a_vartype"
297354

@@ -327,7 +384,7 @@ class RunnerControllerTests : ControllerTestBase() {
327384
parametersValues =
328385
mutableListOf(
329386
RunnerRunTemplateParameterValue(
330-
parameterId = runnerParameterId,
387+
parameterId = solutionParameterId1,
331388
value = runnerParameterValue,
332389
varType = runnerParameterVarType,
333390
isInherited = false)))
@@ -349,15 +406,15 @@ class RunnerControllerTests : ControllerTestBase() {
349406
.andExpect(jsonPath("$.solutionName").value(solutionName))
350407
.andExpect(jsonPath("$.runTemplateName").value(runTemplateName))
351408
.andExpect(jsonPath("$.tags").value(tags))
352-
.andExpect(jsonPath("$.datasetList").value(datasetList))
409+
.andExpect(jsonPath("$.datasets.bases").value(datasetList))
353410
.andExpect(jsonPath("$.security.default").value(ROLE_NONE))
354411
.andExpect(jsonPath("$.runSizing.requests.cpu").value("cpu_requests"))
355412
.andExpect(jsonPath("$.runSizing.requests.memory").value("memory_requests"))
356413
.andExpect(jsonPath("$.runSizing.limits.cpu").value("cpu_limits"))
357414
.andExpect(jsonPath("$.runSizing.limits.memory").value("memory_limits"))
358-
.andExpect(jsonPath("$.parametersValues[0].parameterId").value(runnerParameterId))
415+
.andExpect(jsonPath("$.parametersValues[0].parameterId").value(solutionParameterId1))
359416
.andExpect(jsonPath("$.parametersValues[0].value").value(runnerParameterValue))
360-
.andExpect(jsonPath("$.parametersValues[0].varType").value(runnerParameterVarType))
417+
.andExpect(jsonPath("$.parametersValues[0].varType").value(solutionParameterVarType1))
361418
.andExpect(jsonPath("$.parametersValues[0].isInherited").value(false))
362419
.andExpect(jsonPath("$.security.accessControlList[0].role").value(ROLE_ADMIN))
363420
.andExpect(jsonPath("$.security.accessControlList[0].id").value(PLATFORM_ADMIN_EMAIL))

api/src/integrationTest/resources/application-test.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ csm:
8181
- text/plain
8282
- text/x-yaml
8383
- application/json
84+
solutions:
85+
- application/zip
86+
- application/xml
87+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
88+
- application/x-tika-ooxml
89+
- text/csv
90+
- text/plain
91+
- text/x-yaml
92+
- application/json
8493
authorization:
8594
mail-jwt-claim: "email"
8695
roles-jwt-claim: "userRoles"

runner/src/integrationTest/kotlin/com/cosmotech/runner/service/RunnerServiceIntegrationTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -925,12 +925,12 @@ class RunnerServiceIntegrationTest : CsmTestBase() {
925925
parametersValues = mutableListOf(runTemplateParameterValue2))
926926

927927
val assertThrows =
928-
assertThrows<IllegalArgumentException> {
928+
assertThrows<CsmResourceNotFoundException> {
929929
runnerApiService.createRunner(
930930
organizationSaved.id, workspaceSaved.id, runnerWithWrongRunTemplateId)
931931
}
932932
assertEquals(
933-
"Run Template not found: ${runnerWithWrongRunTemplateId.runTemplateId}",
933+
"Solution run template with id ${runnerWithWrongRunTemplateId.runTemplateId} does not exist",
934934
assertThrows.message)
935935
}
936936

runner/src/main/kotlin/com/cosmotech/runner/service/RunnerService.kt

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,7 @@ class RunnerService(
269269
organizationId = organization!!.id,
270270
workspaceId = workspace!!.id,
271271
ownerName = "init",
272-
datasets =
273-
RunnerDatasets(
274-
bases = mutableListOf(),
275-
parameter = "TODO: Create and set a new dataset Id here"),
272+
datasets = RunnerDatasets(bases = mutableListOf(), parameter = "init"),
276273
parametersValues = mutableListOf(),
277274
lastRunInfo = LastRunInfo(lastRunId = null, lastRunStatus = LastRunStatus.NotStarted),
278275
validationStatus = RunnerValidationStatus.Draft,
@@ -333,6 +330,12 @@ class RunnerService(
333330
DatasetCreateRequest(name = "Dataset attached to ${this.runner.id}"),
334331
emptyArray())
335332

333+
val filteredParameterValues =
334+
useOnlyDefinedParameterValues(
335+
runnerCreateRequest.solutionId,
336+
runnerCreateRequest.runTemplateId,
337+
runnerCreateRequest.parametersValues)
338+
336339
return setValueFrom(
337340
Runner(
338341
runSizing = runnerCreateRequest.runSizing,
@@ -344,7 +347,7 @@ class RunnerService(
344347
RunnerDatasets(
345348
bases = runnerCreateRequest.datasetList ?: mutableListOf(),
346349
parameter = parameterDataset.id),
347-
parametersValues = runnerCreateRequest.parametersValues ?: mutableListOf(),
350+
parametersValues = filteredParameterValues,
348351
parentId = runnerCreateRequest.parentId,
349352
lastRunInfo =
350353
LastRunInfo(
@@ -365,19 +368,29 @@ class RunnerService(
365368
}
366369

367370
fun setValueFrom(runnerUpdateRequest: RunnerUpdateRequest): RunnerInstance {
371+
372+
val runTemplateId = runnerUpdateRequest.runTemplateId ?: this.runner.runTemplateId
373+
374+
val filteredParameterValues =
375+
if (runnerUpdateRequest.parametersValues == null) {
376+
this.runner.parametersValues
377+
} else {
378+
useOnlyDefinedParameterValues(
379+
this.runner.solutionId, runTemplateId, runnerUpdateRequest.parametersValues)
380+
}
381+
368382
return setValueFrom(
369383
Runner(
370384
runSizing = runnerUpdateRequest.runSizing ?: this.runner.runSizing,
371385
tags = runnerUpdateRequest.tags ?: this.runner.tags,
372386
description = runnerUpdateRequest.description ?: this.runner.description,
373387
name = runnerUpdateRequest.name ?: this.runner.name,
374-
runTemplateId = runnerUpdateRequest.runTemplateId ?: this.runner.runTemplateId,
388+
runTemplateId = runTemplateId,
375389
datasets =
376390
RunnerDatasets(
377391
bases = runnerUpdateRequest.datasetList ?: this.runner.datasets.bases,
378392
parameter = this.runner.datasets.parameter),
379-
parametersValues =
380-
runnerUpdateRequest.parametersValues ?: this.runner.parametersValues,
393+
parametersValues = filteredParameterValues,
381394
id = this.runner.id,
382395
organizationId = this.runner.organizationId,
383396
security = this.runner.security,
@@ -484,6 +497,31 @@ class RunnerService(
484497
}
485498
}
486499

500+
private fun useOnlyDefinedParameterValues(
501+
solutionId: String,
502+
runTemplateId: String,
503+
parametersValues: MutableList<RunnerRunTemplateParameterValue>?
504+
): MutableList<RunnerRunTemplateParameterValue> {
505+
if (parametersValues.isNullOrEmpty()) return mutableListOf()
506+
507+
val allowedParametersIds = mutableListOf<String>()
508+
val runTemplateParameterGroups =
509+
solutionApiService
510+
.getRunTemplate(organization!!.id, solutionId, runTemplateId)
511+
.parameterGroups
512+
.toList()
513+
514+
runTemplateParameterGroups.forEach {
515+
val solutionParameterGroup =
516+
solutionApiService.getSolutionParameterGroup(organization!!.id, solutionId, it)
517+
allowedParametersIds.addAll(solutionParameterGroup.parameters)
518+
}
519+
520+
return parametersValues
521+
.filter { allowedParametersIds.contains(it.parameterId) }
522+
.toMutableList()
523+
}
524+
487525
private fun constructDatasetParametersFromParent(
488526
runTemplateParametersIds: List<String>,
489527
parentId: String,

0 commit comments

Comments
 (0)