Skip to content

Commit

Permalink
fix: service copy without default template (#1558)
Browse files Browse the repository at this point in the history
### Motivation
When copying a service without providing a template we try to fallback
to the "<TaskName>/default" template. But our fallback logic is not
working correctly and causing an NPE.

### Modification
We now only accept a single service when copying. If no default template
exists and no template is provided we respond with an message indicating
the missing template.

### Result
The `service <Service> copy` Command is working again.

##### Other context
Fixes #1550
  • Loading branch information
0utplay authored Dec 20, 2024
1 parent d88453f commit af4a659
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@
import eu.cloudnetservice.common.column.RowedFormatter;
import eu.cloudnetservice.common.language.I18n;
import eu.cloudnetservice.common.resource.ResourceFormatter;
import eu.cloudnetservice.common.tuple.Tuple2;
import eu.cloudnetservice.common.util.WildcardUtil;
import eu.cloudnetservice.driver.channel.ChannelMessageSender;
import eu.cloudnetservice.driver.event.EventListener;
import eu.cloudnetservice.driver.event.EventManager;
import eu.cloudnetservice.driver.event.events.service.CloudServiceLogEntryEvent;
import eu.cloudnetservice.driver.provider.CloudServiceProvider;
import eu.cloudnetservice.driver.provider.SpecificCloudServiceProvider;
import eu.cloudnetservice.driver.service.ServiceDeployment;
import eu.cloudnetservice.driver.service.ServiceInfoSnapshot;
import eu.cloudnetservice.driver.service.ServiceRemoteInclusion;
Expand All @@ -51,7 +49,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.NonNull;
import org.incendo.cloud.annotation.specifier.Greedy;
Expand Down Expand Up @@ -203,44 +200,32 @@ public void copyService(
@Nullable @Flag("includes") @Quoted String includes,
@Flag("case-sensitive") boolean caseSensitive
) {
// associate all services with a template
Collection<Tuple2<SpecificCloudServiceProvider, ServiceTemplate>> targets = services.stream()
.map(service -> {
if (template != null) {
return new Tuple2<>(service.provider(), template);
} else {
// find a matching template
return service.configuration().templates().stream()
.filter(st -> st.prefix().equalsIgnoreCase(service.serviceId().taskName()))
.filter(st -> st.name().equalsIgnoreCase("default"))
.map(st -> new Tuple2<>(service.provider(), st))
.findFirst()
.orElse(null);
}
})
.collect(Collectors.toSet());
// check if we found a result
if (targets.isEmpty()) {
source.sendMessage(I18n.trans("command-service-copy-no-default-template"));
return;
var service = services.iterator().next();
var serviceProvider = service.provider();
if (template == null) {
template = serviceProvider.installedTemplates().stream()
.filter(st -> st.prefix().equalsIgnoreCase(service.serviceId().taskName()))
.filter(st -> st.name().equalsIgnoreCase("default"))
.findFirst()
.orElse(null);

if (template == null) {
source.sendMessage(I18n.trans("command-service-copy-no-default-template", service.serviceId().name()));
return;
}
}

// split on a semicolon and try to fix the patterns the user entered
var parsedExcludes = parseDeploymentPatterns(excludes, caseSensitive);
var parsedIncludes = parseDeploymentPatterns(includes, caseSensitive);
for (var target : targets) {
target.first().addServiceDeployment(ServiceDeployment.builder()
.template(target.second())
.excludes(parsedExcludes)
.includes(parsedIncludes)
.withDefaultExclusions()
.build());
target.first().removeAndExecuteDeployments();
// send a message for each service we did copy the template of
//noinspection ConstantConditions
source.sendMessage(I18n.trans("command-service-copy-success",
target.first().serviceInfo().name(),
target.second().toString()));
}
serviceProvider.addServiceDeployment(ServiceDeployment.builder()
.template(template)
.excludes(parsedExcludes)
.includes(parsedIncludes)
.withDefaultExclusions()
.build());
serviceProvider.removeAndExecuteDeployments();
source.sendMessage(I18n.trans("command-service-copy-success", service.serviceId().name(), template));
}

@Command("service|ser <name> delete|del")
Expand Down
2 changes: 1 addition & 1 deletion node/src/main/resources/lang/de_DE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ command-cluster-start-sync=Die Cluster Synchronisation wird gestartet
# Command Service
#
command-service-description=Verwaltet alle Services in dem Cluster
command-service-copy-no-default-template=Der von Dir angegebene Service hat keine default Template. Benutze "copy {0$name$} template\=storage\:prefix/name" um ein Template anzugeben, in das du kopieren möchtest
command-service-copy-no-default-template=Der angegebene Service hat kein default Template. Um ein Template anzugeben kann "service {0$name$} copy --template storage\:prefix/name" verwendet werden
command-service-copy-success=Der Service {0$name$} wurde erfolgreich in das Template {1$template$} kopiert
command-service-add-deployment-success=Das Deployment {0$deployment$} wurde erfolgreich zu der Warteschlange hinzugefügt
command-service-deploy-deployment-success=Die Ressourcen des Services wurden erfolgreich deployed
Expand Down
2 changes: 1 addition & 1 deletion node/src/main/resources/lang/en_US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ command-cluster-start-sync=The cluster sync starts now
# Command Service
#
command-service-description=Manages all services in the cluster
command-service-copy-no-default-template=The service you provided does not have a default template, use "copy {0$name$} template=storage:prefix/name" to provide a template you would like to copy to
command-service-copy-no-default-template=The provided service does not have a default template. To specify a template "service {0$name$} copy --template storage:prefix/name" can be used
command-service-copy-success=The service {0$name$} was successfully copied to the template {1$template$}
command-service-add-deployment-success=The deployment {0$deployment$} was successfully added to the waiting deployments
command-service-deploy-deployment-success=The resources of the service were successfully deployed
Expand Down

0 comments on commit af4a659

Please sign in to comment.