6593 improve usability of deploy new script - #7606
Conversation
227e99c to
a1411a6
Compare
…com:gchq/sleeper into 6593-improve-usability-of-deploy-new-script
| deployPaused = builder.deployPaused; | ||
| public DeployNewInstance(InstanceDeployer deployInstance, | ||
| StoreFactory storeFactory, | ||
| SleeperInstanceConfiguration deployInstanceConfiguration, |
There was a problem hiding this comment.
I'm struggling to understand how this is passed around now, particularly as the path it comes from is passed as separate parameters alongside it.
There was a problem hiding this comment.
This is easier to follow now, but I think it's still a bit confusing.
The InstanceProperties object is currently used as an intermediate data structure just to set the instance ID, VPC and subnets in the CdkCommand. I think that indirection is misleading, and I don't think there's a reason to mix that with the configuration from the files. Is it possible to build the CdkCommand directly from the Arguments object?
The InstanceProperties object is also used when we create the tables, but it's reloaded fresh from the deployed instance. I think it's confusing to reuse the same object for that, when it will contain very different data. We could use InstancePropertiesLoader instead of a reloadInstanceProperties.
That also means I don't think we need to load the whole configuration from the files, just the table properties. I think the only thing we're using the whole configuration for right now is to validate it, but the CDK will do that anyway.
There's also a tension with the original contract where DeployNewInstance is used elsewhere, because previously it was taking a DeployInstanceConfiguration and writing it to disk, but now it doesn't do that any more. We still need the callers to work. We can either just write it to disk if it was provided, or update the callers to write it to disk before they call this class.
Here's a link to the original thread: #7606 (comment)
| void setUp() throws IOException { | ||
| createTempDirectory(tempDir, null); | ||
| instancePropertiesFile = tempDir.resolve("instance.properties"); | ||
| Files.writeString(instancePropertiesFile, instanceProperties.saveAsString()); |
There was a problem hiding this comment.
This is generating an InstanceProperties object with InstancePropertiesTestHelper, and that simulates a pre-deployed instance. It's then writing it to a local file and treating it as a user's configuration file. I don't think it makes sense to treat one as the other, and I'm struggling to follow how these values are used.
There was a problem hiding this comment.
Switched the instance properties being used to one without ID, VPC and Subnets set
There was a problem hiding this comment.
There are a lot more properties that are set in createTestInstanceProperties that won't be set in a file provided by the user. It's still using a simulated pre-deployed instance, when what we want is something a user would write. We expect a user will set as few properties as possible. I think we can start from new InstanceProperties()?
Here's a link to the original thread: #7606 (comment)
…le or confgDir being set
…lProperties to create directories
| Path directory, InstanceProperties instanceProperties, | ||
| Stream<TableProperties> tablePropertiesStream) throws IOException { | ||
| Files.createDirectories(directory); | ||
| FilesUtil.clearDirectory(directory); |
There was a problem hiding this comment.
Is this necessary, surely if its created it fresh then it should be empty?
There was a problem hiding this comment.
createDirectories doesn't fail the directory already exists
There was a problem hiding this comment.
Discussed together and happy with action
| void setUp() throws IOException { | ||
| createTempDirectory(tempDir, null); | ||
| instancePropertiesFile = tempDir.resolve("instance.properties"); | ||
| Files.writeString(instancePropertiesFile, instanceProperties.saveAsString()); |
There was a problem hiding this comment.
There are a lot more properties that are set in createTestInstanceProperties that won't be set in a file provided by the user. It's still using a simulated pre-deployed instance, when what we want is something a user would write. We expect a user will set as few properties as possible. I think we can start from new InstanceProperties()?
Here's a link to the original thread: #7606 (comment)
| return builder().command(command).configurationDirectory(configurationDirectory).arguments(arguments).build(); | ||
| } | ||
|
|
||
| public CdkCommand withNetworkConfiguration(String instanceId, String vpcId, String subnets) { |
There was a problem hiding this comment.
This name seems slightly misleading, since the instance ID isn't part of the network configuration. I don't mind if you'd rather leave it as it is. Another option would be a toBuilder method.
| String subnetIds = args[3]; | ||
| Path instancePropertiesFile = optionalArgument(args, 4).map(Path::of).orElse(null); | ||
| boolean deployPaused = "true".equalsIgnoreCase(optionalArgument(args, 5).orElse("false")); | ||
| public DeployNewInstance(Builder builder) { |
There was a problem hiding this comment.
By our coding conventions, the constructor should be the first method in the file, as it was before.
It looks like the constructor can be private.
| return config; | ||
| } | ||
|
|
||
| public static Arguments readArguments(CommandArguments arguments) { |
There was a problem hiding this comment.
I think it would be nice to keep this function right next to the usage constant, because you'll want to check it agrees with that about the names of the parameters. I think loadConfiguration can be below this.
| deployPaused = builder.deployPaused; | ||
| public DeployNewInstance(InstanceDeployer deployInstance, | ||
| StoreFactory storeFactory, | ||
| SleeperInstanceConfiguration deployInstanceConfiguration, |
There was a problem hiding this comment.
This is easier to follow now, but I think it's still a bit confusing.
The InstanceProperties object is currently used as an intermediate data structure just to set the instance ID, VPC and subnets in the CdkCommand. I think that indirection is misleading, and I don't think there's a reason to mix that with the configuration from the files. Is it possible to build the CdkCommand directly from the Arguments object?
The InstanceProperties object is also used when we create the tables, but it's reloaded fresh from the deployed instance. I think it's confusing to reuse the same object for that, when it will contain very different data. We could use InstancePropertiesLoader instead of a reloadInstanceProperties.
That also means I don't think we need to load the whole configuration from the files, just the table properties. I think the only thing we're using the whole configuration for right now is to validate it, but the CDK will do that anyway.
There's also a tension with the original contract where DeployNewInstance is used elsewhere, because previously it was taking a DeployInstanceConfiguration and writing it to disk, but now it doesn't do that any more. We still need the callers to work. We can either just write it to disk if it was provided, or update the callers to write it to disk before they call this class.
Here's a link to the original thread: #7606 (comment)
| config.getInstanceProperties().set(SUBNETS, subnets); | ||
| } | ||
|
|
||
| private DeployInstanceRequest buildExpectedCDKCommandWithPropertyFile(SleeperInstanceConfiguration config, boolean deployPaused) { |
There was a problem hiding this comment.
This is duplicating the implementation. Please make the asserted value explicit.
| .build(); | ||
| } | ||
|
|
||
| private DeployInstanceRequest buildExpectedCDKCommandWithConfigDir(SleeperInstanceConfiguration config, boolean deployPaused) { |
There was a problem hiding this comment.
This is duplicating the implementation. Please make the asserted value explicit.
| assertThat(deployRequests.size()).isEqualTo(1); | ||
| DeployInstanceRequest lastDeployRequest = deployRequests.get(0); | ||
| assertThat(lastDeployRequest).usingRecursiveComparison() | ||
| .isEqualTo(buildExpectedCDKCommandWithPropertyFile(config, false)); |
There was a problem hiding this comment.
This two assertions can be one, with assertThat(...).containsExactly.
I don't think usingRecursiveComparison is necessary? CdkCommand is a record.
This also applies to the other tests.
| .storeFactory(StoreFactory.withAwsClients(s3Client, dynamoClient, accountName)) | ||
| .deployInstanceConfiguration(config) | ||
| .cdkApp(SleeperInternalCdkApp.DEMONSTRATION) | ||
| .cdkApp(SleeperInternalCdkApp.STANDARD) |
There was a problem hiding this comment.
This is setting the wrong CDK app.
| .deployInstanceConfiguration(config) | ||
| .cdkApp(SleeperInternalCdkApp.DEMONSTRATION) | ||
| .cdkApp(SleeperInternalCdkApp.STANDARD) | ||
| .configDir(configurationPath) |
There was a problem hiding this comment.
This is not correct. The code above is deriving the instance configuration from templates, but this is pointing to the original configuration file instead. I think this script still needs to write the files to a generated directory and point to that.
patchwork01
left a comment
There was a problem hiding this comment.
It looks like the demonstration deployment is broken right now, and I'm struggling to review the tests.
Make sure you have checked all steps below.
Issue
Feature". Note that before an issue is finished, you can still make a pull request by raising a separate issue
for your progress.
Tests
Documentation
separate issue for that below.