-
Notifications
You must be signed in to change notification settings - Fork 807
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): Delegate task/stage lookup to
TaskResolver
and `StageRe…
…solver` respectively (#2868) The `*Resolver` implementations will be able to look at both raw implementation classes _as well as_ any specified aliases. This supports (currently unsupported!) use cases that would be made easier if a `Task` or `StageDefinitionBuilder` could be renamed.
- Loading branch information
Showing
28 changed files
with
616 additions
and
86 deletions.
There are no files selected for viewing
94 changes: 94 additions & 0 deletions
94
orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright 2019 Netflix, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.spinnaker.orca; | ||
|
||
import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder; | ||
|
||
import javax.annotation.Nonnull; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static java.lang.String.format; | ||
|
||
/** | ||
* {@code StageResolver} allows for {@code StageDefinitionBuilder} retrieval via bean name or alias. | ||
* <p> | ||
* Aliases represent the previous bean names that a {@code StageDefinitionBuilder} registered as. | ||
*/ | ||
public class StageResolver { | ||
private final Map<String, StageDefinitionBuilder> stageDefinitionBuilderByAlias = new HashMap<>(); | ||
|
||
public StageResolver(Collection<StageDefinitionBuilder> stageDefinitionBuilders) { | ||
for (StageDefinitionBuilder stageDefinitionBuilder : stageDefinitionBuilders) { | ||
stageDefinitionBuilderByAlias.put(stageDefinitionBuilder.getType(), stageDefinitionBuilder); | ||
for (String alias : stageDefinitionBuilder.aliases()) { | ||
if (stageDefinitionBuilderByAlias.containsKey(alias)) { | ||
throw new DuplicateStageAliasException( | ||
format( | ||
"Duplicate stage alias detected (alias: %s, previous: %s, current: %s)", | ||
alias, | ||
stageDefinitionBuilderByAlias.get(alias).getClass().getCanonicalName(), | ||
stageDefinitionBuilder.getClass().getCanonicalName() | ||
) | ||
); | ||
} | ||
|
||
stageDefinitionBuilderByAlias.put(alias, stageDefinitionBuilder); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Fetch a {@code StageDefinitionBuilder} by {@param type} or {@param typeAlias}. | ||
* | ||
* @param type StageDefinitionBuilder type | ||
* @param typeAlias StageDefinitionBuilder alias (optional) | ||
* @return the StageDefinitionBuilder matching {@param type} or {@param typeAlias} | ||
* @throws NoSuchStageDefinitionBuilderException if StageDefinitionBuilder does not exist | ||
*/ | ||
@Nonnull | ||
public StageDefinitionBuilder getStageDefinitionBuilder(@Nonnull String type, String typeAlias) { | ||
StageDefinitionBuilder stageDefinitionBuilder = stageDefinitionBuilderByAlias.getOrDefault( | ||
type, stageDefinitionBuilderByAlias.get(typeAlias) | ||
); | ||
|
||
if (stageDefinitionBuilder == null) { | ||
throw new NoSuchStageDefinitionBuilderException(type, stageDefinitionBuilderByAlias.keySet()); | ||
} | ||
|
||
return stageDefinitionBuilder; | ||
} | ||
|
||
class DuplicateStageAliasException extends IllegalStateException { | ||
DuplicateStageAliasException(String message) { | ||
super(message); | ||
} | ||
} | ||
|
||
class NoSuchStageDefinitionBuilderException extends IllegalArgumentException { | ||
NoSuchStageDefinitionBuilderException(String type, Collection<String> knownTypes) { | ||
super( | ||
format( | ||
"No StageDefinitionBuilder implementation for %s found (knownTypes: %s)", | ||
type, | ||
String.join(",", knownTypes) | ||
) | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
orca-core/src/main/java/com/netflix/spinnaker/orca/TaskResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* Copyright 2019 Netflix, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.spinnaker.orca; | ||
|
||
import com.google.common.annotations.VisibleForTesting; | ||
|
||
import javax.annotation.Nonnull; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static java.lang.String.format; | ||
|
||
/** | ||
* {@code TaskResolver} allows for {@code Task} retrieval via class name or alias. | ||
* <p> | ||
* Aliases represent the previous class names of a {@code Task}. | ||
*/ | ||
public class TaskResolver { | ||
private final Map<String, Task> taskByAlias = new HashMap<>(); | ||
|
||
private final boolean allowFallback; | ||
|
||
@VisibleForTesting | ||
public TaskResolver(Collection<Task> tasks) { | ||
this(tasks, true); | ||
} | ||
|
||
/** | ||
* @param tasks Task implementations | ||
* @param allowFallback Fallback to {@code Class.forName()} if a task cannot be located by name or alias | ||
*/ | ||
public TaskResolver(Collection<Task> tasks, boolean allowFallback) { | ||
for (Task task : tasks) { | ||
taskByAlias.put(task.getClass().getCanonicalName(), task); | ||
for (String alias : task.aliases()) { | ||
if (taskByAlias.containsKey(alias)) { | ||
throw new DuplicateTaskAliasException( | ||
String.format( | ||
"Duplicate task alias detected (alias: %s, previous: %s, current: %s)", | ||
alias, | ||
taskByAlias.get(alias).getClass().getCanonicalName(), | ||
task.getClass().getCanonicalName() | ||
) | ||
); | ||
} | ||
|
||
taskByAlias.put(alias, task); | ||
} | ||
} | ||
|
||
this.allowFallback = allowFallback; | ||
} | ||
|
||
/** | ||
* Fetch a {@code Task} by {@param taskTypeIdentifier}. | ||
* | ||
* @param taskTypeIdentifier Task identifier (class name or alias) | ||
* @return the Task matching {@param taskTypeIdentifier} | ||
* @throws NoSuchTaskException if Task does not exist | ||
*/ | ||
@Nonnull | ||
public Task getTask(@Nonnull String taskTypeIdentifier) { | ||
Task task = taskByAlias.get(taskTypeIdentifier); | ||
|
||
if (task == null) { | ||
throw new NoSuchTaskException(taskTypeIdentifier); | ||
} | ||
|
||
return task; | ||
} | ||
|
||
/** | ||
* @param taskTypeIdentifier Task identifier (class name or alias) | ||
* @return Task Class | ||
* @throws NoSuchTaskException if task does not exist | ||
*/ | ||
@Nonnull | ||
public Class<? extends Task> getTaskClass(@Nonnull String taskTypeIdentifier) { | ||
try { | ||
return getTask(taskTypeIdentifier).getClass(); | ||
} catch (IllegalArgumentException e) { | ||
if (!allowFallback) { | ||
throw e; | ||
} | ||
|
||
try { | ||
return (Class<? extends Task>) Class.forName(taskTypeIdentifier); | ||
} catch (ClassNotFoundException ex) { | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
class DuplicateTaskAliasException extends IllegalStateException { | ||
DuplicateTaskAliasException(String message) { | ||
super(message); | ||
} | ||
} | ||
|
||
class NoSuchTaskException extends IllegalArgumentException { | ||
NoSuchTaskException(String taskTypeIdentifier) { | ||
super("No task found for '" + taskTypeIdentifier + "'"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.