-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #206 from perfectsense/feature/ec2-placement-groups
EC2 Placement Groups
- Loading branch information
Showing
4 changed files
with
297 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
aws::placement-group example-placement-group | ||
name: "TestGroup" | ||
placement-strategy: "partition" | ||
partition-count: 3 | ||
end |
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,88 @@ | ||
/* | ||
* Copyright 2020, Perfect Sense, 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 gyro.aws.ec2; | ||
|
||
import gyro.core.Type; | ||
import gyro.core.finder.Filter; | ||
import software.amazon.awssdk.services.ec2.Ec2Client; | ||
import software.amazon.awssdk.services.ec2.model.PlacementGroup; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* Query placement groups. | ||
* | ||
* Example | ||
* ------- | ||
* | ||
* .. code-block:: gyro | ||
* | ||
* pg: $(external-query aws::placement-group {name: "placement-group-example", state: "available", strategy: "spread" }) | ||
*/ | ||
@Type("placement-group") | ||
public class PlacementGroupFinder extends Ec2TaggableAwsFinder<Ec2Client, PlacementGroup, PlacementGroupResource> { | ||
|
||
private String name; | ||
private String state; | ||
private String strategy; | ||
|
||
/** | ||
* The name of the Placement Group. | ||
*/ | ||
@Filter("group-name") | ||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
/** | ||
* The state of the Placement Group. Valid values are ``pending``, ``available``, ``deleting`` or ``deleted``. | ||
*/ | ||
public String getState() { | ||
return state; | ||
} | ||
|
||
public void setState(String state) { | ||
this.state = state; | ||
} | ||
|
||
/** | ||
* Approaches towards managing the placement of instances on the underlying hardware. Valid values are ``cluster``, ``spread`` or ``partition``. | ||
*/ | ||
public String getStrategy() { | ||
return strategy; | ||
} | ||
|
||
public void setStrategy(String strategy) { | ||
this.strategy = strategy; | ||
} | ||
|
||
@Override | ||
protected List<PlacementGroup> findAllAws(Ec2Client client) { | ||
return client.describePlacementGroups().placementGroups().stream().collect(Collectors.toList()); | ||
} | ||
|
||
@Override | ||
protected List<PlacementGroup> findAws(Ec2Client client, Map<String, String> filters) { | ||
return client.describePlacementGroups(r -> r.filters(createFilters(filters))).placementGroups().stream().collect(Collectors.toList()); | ||
} | ||
} |
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,203 @@ | ||
/* | ||
* Copyright 2020, Perfect Sense, 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 gyro.aws.ec2; | ||
|
||
import com.psddev.dari.util.ObjectUtils; | ||
import gyro.aws.AwsResource; | ||
import gyro.aws.Copyable; | ||
import gyro.core.GyroException; | ||
import gyro.core.GyroUI; | ||
import gyro.core.Type; | ||
import gyro.core.resource.Id; | ||
import gyro.core.resource.Output; | ||
import gyro.core.scope.State; | ||
import gyro.core.validation.Range; | ||
import gyro.core.validation.Required; | ||
import gyro.core.validation.ValidationError; | ||
import software.amazon.awssdk.services.ec2.Ec2Client; | ||
import software.amazon.awssdk.services.ec2.model.*; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* Creates a Placement Group with the specified name and placement strategy. | ||
* | ||
* Example | ||
* ------- | ||
* | ||
* .. code-block:: gyro | ||
* | ||
* aws::placement-group example-placement-group | ||
* name: "TestGroup" | ||
* placement-strategy: "partition" | ||
* partition-count: 3 | ||
* end | ||
*/ | ||
@Type("placement-group") | ||
public class PlacementGroupResource extends Ec2TaggableResource<PlacementGroup> implements Copyable<PlacementGroup> { | ||
|
||
private String name; | ||
private PlacementStrategy placementStrategy; | ||
private Integer partitionCount; | ||
|
||
// Read-only | ||
private String id; | ||
|
||
/** | ||
* The name of the Placement Group. (Required) | ||
*/ | ||
@Required | ||
public String getName() { | ||
return name; | ||
} | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
/** | ||
* Approaches towards managing the placement of instances on the underlying hardware. Valid values are ``cluster``, ``spread`` or ``partition``. | ||
* Defaults to the``cluster`` strategy. (Required) | ||
*/ | ||
@Required | ||
public PlacementStrategy getPlacementStrategy() { | ||
return placementStrategy; | ||
} | ||
|
||
public void setPlacementStrategy(PlacementStrategy placementStrategy) { | ||
this.placementStrategy = placementStrategy; | ||
} | ||
|
||
/** | ||
* The number of partitions comprising the Placement Group. Valid values are within 1 to 7. Only required when strategy is set to ``partition``. | ||
*/ | ||
@Range(min= 1, max= 7) | ||
public Integer getPartitionCount() { | ||
return partitionCount; | ||
} | ||
|
||
public void setPartitionCount(Integer partitionCount) { | ||
this.partitionCount = partitionCount; | ||
} | ||
|
||
/** | ||
* The ID of the Placement Group. | ||
*/ | ||
@Id | ||
@Output | ||
public String getId() { | ||
return id; | ||
} | ||
|
||
public void setId(String id) { | ||
this.id = id; | ||
} | ||
|
||
@Override | ||
protected String getResourceId() { | ||
return getId(); | ||
} | ||
|
||
@Override | ||
public void copyFrom(PlacementGroup model) { | ||
setId(model.groupId()); | ||
setName(model.groupName()); | ||
setPlacementStrategy(model.strategy()); | ||
setPartitionCount(model.partitionCount()); | ||
refreshTags(); | ||
} | ||
|
||
@Override | ||
public boolean doRefresh() { | ||
Ec2Client client = createClient(Ec2Client.class); | ||
|
||
if (ObjectUtils.isBlank(getName())) { | ||
throw new GyroException("name is missing, unable to load placement group."); | ||
} | ||
|
||
PlacementGroup group = getPlacementGroup(client); | ||
|
||
if (group == null) { | ||
return false; | ||
} | ||
|
||
copyFrom(group); | ||
return true; | ||
} | ||
|
||
@Override | ||
protected void doCreate(GyroUI ui, State state) { | ||
Ec2Client client = createClient(Ec2Client.class); | ||
|
||
client.createPlacementGroup(r -> r.groupName(getName()) | ||
.strategy(getPlacementStrategy()) | ||
.partitionCount(getPartitionCount())); | ||
|
||
PlacementGroup group = getPlacementGroup(client); | ||
|
||
if (group != null) { | ||
setId(group.groupId()); | ||
} | ||
|
||
} | ||
|
||
@Override | ||
protected void doUpdate(GyroUI ui, State state, AwsResource config, Set<String> changedProperties) { | ||
|
||
} | ||
|
||
@Override | ||
public void delete(GyroUI ui, State state) throws Exception { | ||
Ec2Client client = createClient(Ec2Client.class); | ||
client.deletePlacementGroup(r -> r.groupName(getName())); | ||
} | ||
|
||
@Override | ||
public List<ValidationError> validate(Set<String> configuredFields) { | ||
List<ValidationError> errors = new ArrayList<>(); | ||
|
||
if ((getPlacementStrategy() == PlacementStrategy.PARTITION) && (getPartitionCount() == null)) { | ||
ValidationError error = new ValidationError(this, "partition-count", "partition-count is required when strategy is set to 'partition'"); | ||
errors.add(error); | ||
|
||
} else if ((getPlacementStrategy() != PlacementStrategy.PARTITION) && (getPartitionCount() != null)) { | ||
ValidationError error = new ValidationError(this, "partition-count", "partition-count must not be set when strategy is not set to 'partition'"); | ||
errors.add(error); | ||
} | ||
|
||
return errors; | ||
} | ||
|
||
private PlacementGroup getPlacementGroup(Ec2Client client) { | ||
PlacementGroup group = null; | ||
try { | ||
DescribePlacementGroupsResponse describeResponse = client.describePlacementGroups(r -> r.groupNames(getName())); | ||
if (!describeResponse.placementGroups().isEmpty()) { | ||
group = describeResponse.placementGroups().get(0); | ||
} | ||
|
||
} catch (Ec2Exception ex) { | ||
if (ex.awsErrorDetails() == null || !ex.awsErrorDetails().errorCode().equals("InvalidPlacementGroup.Unknown")) { | ||
throw ex; | ||
} | ||
} | ||
|
||
return group; | ||
} | ||
} |