From fdd82170efe9ea5ea812c25700b65cdc48021794 Mon Sep 17 00:00:00 2001 From: Bruno Agostinho Date: Thu, 28 Dec 2023 18:45:26 -0300 Subject: [PATCH 01/10] Initial work --- .../orion/core/actions/aws/AmiTagManager.java | 81 ++++++ .../com/pinterest/orion/server/api/AMI.java | 25 ++ .../orion/server/api/ClusterManagerApi.java | 31 ++ .../resources/webapp/src/actions/cluster.js | 24 ++ .../webapp/src/basic-components/AMI.js | 269 ++++++++++++++++++ .../webapp/src/basic-components/Homepage.js | 6 + .../main/resources/webapp/src/reducers/app.js | 4 +- .../main/resources/webapp/src/sagas/index.js | 41 +++ 8 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java create mode 100644 orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java create mode 100644 orion-server/src/main/resources/webapp/src/basic-components/AMI.js diff --git a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java new file mode 100644 index 00000000..5eb47404 --- /dev/null +++ b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java @@ -0,0 +1,81 @@ +package com.pinterest.orion.core.actions.aws; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import com.pinterest.orion.server.api.AMI; +import com.pinterest.orion.server.api.BaseClustersApi; + +import software.amazon.awssdk.services.ec2.Ec2Client; +import software.amazon.awssdk.services.ec2.model.DescribeImagesRequest; +import software.amazon.awssdk.services.ec2.model.DescribeImagesResponse; +import software.amazon.awssdk.services.ec2.model.CreateTagsRequest; +import software.amazon.awssdk.services.ec2.model.CreateTagsResponse; +import software.amazon.awssdk.services.ec2.model.Filter; +import software.amazon.awssdk.services.ec2.model.Tag; + +public class AmiTagManager { + private static final Logger logger = Logger.getLogger(AmiTagManager.class.getCanonicalName()); + private Ec2Client ec2Client; + + public AmiTagManager() { + ec2Client = Ec2Client.create(); + } + + public List getAmiList(Map filter) { + List amiList = new ArrayList<>(); + DescribeImagesRequest.Builder builder = DescribeImagesRequest.builder(); + builder = builder.filters( + Filter.builder().name("tag:application").values("kafka").build() + ); + if (filter.containsKey("os")) + builder = builder.filters( + Filter.builder().name("tag:release").values(filter.get("os")).build() + ); + if (filter.containsKey("arch")) + builder = builder.filters( + Filter.builder().name("tag:cpu_architecture").values(filter.get("arch")).build() + ); + builder = builder.filters( + Filter.builder().name("tag:application_environment").values("*").build() + ); + DescribeImagesResponse resp = ec2Client.describeImages(builder.build()); + if (resp.hasImages() && !resp.images().isEmpty()) { + resp.images().forEach(image -> { + Iterator i = image.tags().iterator(); + Tag t; + String appEnvTag = null; + while (i.hasNext()) { + t = i.next(); + if (t.key().equals("application_environment")) { + appEnvTag = t.value(); + break; + } + } + amiList.add(new AMI( + image.imageId(), + appEnvTag, + image.creationDate() + )); + }); + } + return amiList; + } + + public void updateAmiTag(String amiId, String applicationEnvironment) { + CreateTagsRequest.Builder builder = CreateTagsRequest.builder(); + Tag newAppEnv = Tag.builder() + .key("application_environment") + .value(applicationEnvironment).build(); + CreateTagsRequest request = builder + .resources(amiId) + .tags(newAppEnv) + .build(); + CreateTagsResponse resp = ec2Client.createTags(request); + if (!resp.sdkHttpResponse().isSuccessful()) + logger.severe("Tag update failed for " + amiId + " and application_environment tag = " + applicationEnvironment); + } +} diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java new file mode 100644 index 00000000..06dc91a0 --- /dev/null +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java @@ -0,0 +1,25 @@ +package com.pinterest.orion.server.api; + +public class AMI { + private final String amiId; + private final String applicationEnvironment; + private final String creationDate; + + public AMI(String amiId, String applicationEnvironment, String creationDate) { + this.amiId = amiId; + this.applicationEnvironment = applicationEnvironment; + this.creationDate = creationDate; + } + + public String getAmiId() { + return amiId; + } + + public String getApplicationEnvironment() { + return applicationEnvironment; + } + + public String getCreationDate() { + return creationDate; + } +} diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java b/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java index 4157b5ec..478f7ab0 100644 --- a/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java @@ -25,9 +25,11 @@ import javax.annotation.security.RolesAllowed; import javax.ws.rs.GET; +import javax.ws.rs.PUT; import javax.ws.rs.NotFoundException; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.SecurityContext; @@ -41,11 +43,13 @@ import com.pinterest.orion.core.Utilization; import com.pinterest.orion.core.global.sensor.GlobalPluginManager; import com.pinterest.orion.core.global.sensor.GlobalSensor; +import com.pinterest.orion.core.actions.aws.AmiTagManager; import com.pinterest.orion.server.config.OrionConf; @Path("/") @Produces({ MediaType.APPLICATION_JSON }) public class ClusterManagerApi extends BaseClustersApi { + private AmiTagManager amiTagManager; public ClusterManagerApi(ClusterManager mgr) { super(mgr); @@ -111,6 +115,33 @@ public Map> getUtilizationDetailsByCluster() { return utilizationMap; } + @Path("/describeImages") + @GET + public List describeImages( + @QueryParam("os") String os, + @QueryParam("arch") String arch + ) { + Map filter = new HashMap<>(); + if (os != null) + filter.put("os", os); + if (arch != null) + filter.put("arch", arch); + if (amiTagManager == null) + amiTagManager = new AmiTagManager(); + return amiTagManager.getAmiList(filter); + } + + @Path("/updateImageTag") + @PUT + public void updateImageTag( + @QueryParam("ami_id") String amiId, + @QueryParam("application_environment") String applicationEnvironment + ) { + if (amiTagManager == null) + amiTagManager = new AmiTagManager(); + amiTagManager.updateAmiTag(amiId, applicationEnvironment); + } + @RolesAllowed({ OrionConf.ADMIN_ROLE, OrionConf.MGMT_ROLE }) @Path("/costByCluster") @GET diff --git a/orion-server/src/main/resources/webapp/src/actions/cluster.js b/orion-server/src/main/resources/webapp/src/actions/cluster.js index d42caa55..76d4c6e6 100644 --- a/orion-server/src/main/resources/webapp/src/actions/cluster.js +++ b/orion-server/src/main/resources/webapp/src/actions/cluster.js @@ -30,6 +30,9 @@ export const UTILIZATION_REQUESTED = "UTILIZATION_REQUESTED"; export const UTILIZATION_RECEIVED = "UTILIZATION_RECEIVED"; export const COST_REQUESTED = "COST_REQUESTED"; export const COST_RECEIVED = "COST_RECEIVED"; +export const AMILIST_REQUESTED = "AMILIST_REQUESTED"; +export const AMILIST_RECEIVED = "AMILIST_RECEIVED"; +export const AMITAG_UPDATE = "AMITAG_UPDATE"; export function requestCluster(clusterId) { return { type: CLUSTER_REQUESTED, payload: { clusterId } }; @@ -110,3 +113,24 @@ export function receiveClusterEndpoint(clusterId, field, data) { payload: { clusterId, field, data }, }; } + +export function requestAmiList(filter) { + return { + type: AMILIST_REQUESTED, + payload: { filter }, + }; +} + +export function receiveAmiList(amiList) { + return { + type: AMILIST_RECEIVED, + payload: { amiList }, + }; +} + +export function updateAmiTag(amiId, applicationEnvironment) { + return { + type: AMITAG_UPDATE, + payload: { amiId, applicationEnvironment }, + }; +} diff --git a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js new file mode 100644 index 00000000..2f4a305c --- /dev/null +++ b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright 2020 Pinterest, 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. + *******************************************************************************/ +import React from "react"; +import { Button, FormControl, Grid, InputLabel, MenuItem, Select, TextField, + Table, TableBody, TableCell, TableContainer, TableHead, TableRow, + FormGroup, FormControlLabel, Checkbox } from '@material-ui/core'; +import { makeStyles } from "@material-ui/core/styles"; +import { connect } from "react-redux"; +import { requestAmiList, updateAmiTag } from "../actions/cluster"; + +const mapState = (state, ownProps) => { + const { amiList } = state.app; + return { + ...ownProps, + amiList, + }; +}; + +const mapDispatch = { + requestAmiList, + updateAmiTag +}; + +const useStyles = makeStyles(theme => ({ + formControl: { + margin: theme.spacing(1), + minWidth: 120 + }, +})); + +function AMI({ amiList, requestAmiList, updateAmiTag }) { + const classes = useStyles(); + const [os, setOS] = React.useState(); + const handleOSChange = event => { + setOS(event.target.value); + }; + const [cpuArch, setCPUArch] = React.useState(); + const handleCPUArchChange = event => { + setCPUArch(event.target.value); + }; + const [selected, setSelected] = React.useState([]); + const handleTableRowSelect = (id, row) => { + setSelected(id); + setAppEnv(row.applicationEnvironment); + const envs_str = row.applicationEnvironment; + const envs = envs_str.split(','); + env.dev = env.test = env.staging = env.prod = false; + for (const env_str of envs) + env[env_str] = true; + }; + const [appEnv, setAppEnv] = React.useState(); + const handleAppEnvChange = event => { + setAppEnv(event.target.value); + }; + const [env] = React.useState({ + dev: false, + test: false, + staging: false, + prod: false, + }); + const handleCheckboxChange = (event) => { + env[event.target.name] = event.target.checked; + const newAppEnv = []; + if (env.dev) + newAppEnv.push("dev"); + if (env.test) + newAppEnv.push("test"); + if (env.staging) + newAppEnv.push("staging"); + if (env.prod) + newAppEnv.push("prod"); + setAppEnv(newAppEnv.join(',')); + }; + const applyFilter = () => { + const parms = []; + if (os) + parms.push("os=" + os); + if (cpuArch) + parms.push("arch=" + cpuArch); + requestAmiList(parms.join('&')); + } + + if (!amiList) + amiList = []; + return ( +
+ + +

Tag filters

+
+ + + +
+
+ + OS + + +
+
+ + CPU Architecture + + +
+
+ + + +
+
+ + + +
+
+ + + + + + AMI Id + application_environment + Creation Date + + + + { amiList.map((row) => ( + handleTableRowSelect(row.amiId, row)} + selected={selected === row.amiId} + > + {row.amiId} + {row.applicationEnvironment} + {row.creationDate} + + ))} + +
+
+
+ +
+ +
+
+ + } + label="dev" + /> + } + label="test" + /> + } + label="staging" + /> + } + label="prod" + /> + +
+
+ + + +
+
+
+
+ ); +} + +export default connect(mapState, mapDispatch)(AMI); diff --git a/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js b/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js index 15ba874e..6696bacb 100644 --- a/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js +++ b/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js @@ -26,6 +26,7 @@ import { } from "@material-ui/core"; import Summary from "./Summary"; import Utilization from "./Utilization"; +import AMI from "./AMI"; const routes = [ { @@ -38,6 +39,11 @@ const routes = [ component: Utilization, label: "Utilization", }, + { + subpath: "ami", + component: AMI, + label: "AMI", + }, ]; export default function Homepage(props) { diff --git a/orion-server/src/main/resources/webapp/src/reducers/app.js b/orion-server/src/main/resources/webapp/src/reducers/app.js index 1d77a4bd..e8d8276e 100644 --- a/orion-server/src/main/resources/webapp/src/reducers/app.js +++ b/orion-server/src/main/resources/webapp/src/reducers/app.js @@ -22,7 +22,7 @@ import { AUTO_REFRESH_ENABLED, AUTO_REFRESH_DISABLED, } from "../actions/app"; -import { UTILIZATION_RECEIVED, COST_RECEIVED } from "../actions/cluster"; +import { UTILIZATION_RECEIVED, COST_RECEIVED, AMILIST_RECEIVED } from "../actions/cluster"; export default function showError( state = { @@ -52,6 +52,8 @@ export default function showError( return { ...state, utilization: action.payload.utilization }; case COST_RECEIVED: return { ...state, cost: action.payload.cost }; + case AMILIST_RECEIVED: + return { ...state, amiList: action.payload.amiList }; default: return state; } diff --git a/orion-server/src/main/resources/webapp/src/sagas/index.js b/orion-server/src/main/resources/webapp/src/sagas/index.js index 22071218..af0d4992 100644 --- a/orion-server/src/main/resources/webapp/src/sagas/index.js +++ b/orion-server/src/main/resources/webapp/src/sagas/index.js @@ -38,6 +38,9 @@ import { receiveUtilization, COST_REQUESTED, receiveCost, + AMILIST_REQUESTED, + receiveAmiList, + AMITAG_UPDATE } from "../actions/cluster"; import { CLUSTERS_SUMMARY_REQUESTED, @@ -66,6 +69,8 @@ export default function* rootSaga() { yield fork(utilizationWatcher); yield fork(costWatcher); yield fork(globalSensorWatcher); + yield fork(amiListWatcher); + yield fork(amiTagUpdateWatcher); } function* clusterSummaryWatcher() { @@ -92,6 +97,14 @@ function* globalSensorWatcher() { yield takeEvery(GLOBAL_SENSOR_REQUESTED, fetchGlobalSensors); } +function* amiListWatcher() { + yield takeEvery(AMILIST_REQUESTED, fetchAmiList); +} + +function* amiTagUpdateWatcher() { + yield takeEvery(AMITAG_UPDATE, fetchAmiTagUpdate); +} + function* fetchCost() { try { const resp = yield fetch("/api/costByCluster"); @@ -227,3 +240,31 @@ function* fetchClusterCustomEndpoint(action) { yield put(hideLoading()); } } + +function* fetchAmiList(action) { + const filter = action.payload.filter; + try { + yield put(showLoading()); + const resp = yield call(fetch, "/api/describeImages?" + filter); + const data = yield resp.json(); + yield put(receiveAmiList(data)); + } catch (e) { + yield put(showAppError(e)); + } finally { + yield put(hideLoading()); + } +} + +function* fetchAmiTagUpdate(action) { + const amiId = action.payload.amiId; + const applicationEnvironment = action.payload.applicationEnvironment; + try { + yield put(showLoading()); + yield call(fetch, "/api/updateImageTag?ami_id=" + amiId + + "&application_environment=" + applicationEnvironment, { method: 'PUT' }); + } catch (e) { + yield put(showAppError(e)); + } finally { + yield put(hideLoading()); + } +} From d93854e9060b82a8372d5f051e7239d6fab157ad Mon Sep 17 00:00:00 2001 From: brunoasr Date: Wed, 3 Jan 2024 14:59:15 -0300 Subject: [PATCH 02/10] Fix list sorting --- .../orion/core/actions/aws/AmiTagManager.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java index 5eb47404..78367233 100644 --- a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java +++ b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java @@ -1,5 +1,7 @@ package com.pinterest.orion.core.actions.aws; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -7,7 +9,6 @@ import java.util.logging.Logger; import com.pinterest.orion.server.api.AMI; -import com.pinterest.orion.server.api.BaseClustersApi; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.DescribeImagesRequest; @@ -44,23 +45,28 @@ public List getAmiList(Map filter) { ); DescribeImagesResponse resp = ec2Client.describeImages(builder.build()); if (resp.hasImages() && !resp.images().isEmpty()) { + ZonedDateTime cutDate = ZonedDateTime.now().minusDays(180); resp.images().forEach(image -> { - Iterator i = image.tags().iterator(); - Tag t; - String appEnvTag = null; - while (i.hasNext()) { - t = i.next(); - if (t.key().equals("application_environment")) { - appEnvTag = t.value(); - break; + if (ZonedDateTime.parse(image.creationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME).isAfter(cutDate)) { + Iterator i = image.tags().iterator(); + Tag t; + String appEnvTag = null; + while (i.hasNext()) { + t = i.next(); + if (t.key().equals("application_environment")) { + appEnvTag = t.value(); + break; + } } + amiList.add(new AMI( + image.imageId(), + appEnvTag, + image.creationDate() + )); } - amiList.add(new AMI( - image.imageId(), - appEnvTag, - image.creationDate() - )); }); + amiList.sort((a, b) -> - ZonedDateTime.parse(a.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME) + .compareTo(ZonedDateTime.parse(b.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME))); } return amiList; } From bd2606dd93f0bce6c5421b4b644d6dd03b834d6e Mon Sep 17 00:00:00 2001 From: brunoasr Date: Mon, 29 Jan 2024 22:39:21 -0300 Subject: [PATCH 03/10] Handle exceptions --- .../orion/core/actions/aws/AmiTagManager.java | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java index 78367233..05cbacfa 100644 --- a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java +++ b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java @@ -6,10 +6,12 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.logging.Level; import java.util.logging.Logger; import com.pinterest.orion.server.api.AMI; +import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.DescribeImagesRequest; import software.amazon.awssdk.services.ec2.model.DescribeImagesResponse; @@ -43,30 +45,35 @@ public List getAmiList(Map filter) { builder = builder.filters( Filter.builder().name("tag:application_environment").values("*").build() ); - DescribeImagesResponse resp = ec2Client.describeImages(builder.build()); - if (resp.hasImages() && !resp.images().isEmpty()) { - ZonedDateTime cutDate = ZonedDateTime.now().minusDays(180); - resp.images().forEach(image -> { - if (ZonedDateTime.parse(image.creationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME).isAfter(cutDate)) { - Iterator i = image.tags().iterator(); - Tag t; - String appEnvTag = null; - while (i.hasNext()) { - t = i.next(); - if (t.key().equals("application_environment")) { - appEnvTag = t.value(); - break; + try { + DescribeImagesResponse resp = ec2Client.describeImages(builder.build()); + if (resp.hasImages() && !resp.images().isEmpty()) { + ZonedDateTime cutDate = ZonedDateTime.now().minusDays(180); + resp.images().forEach(image -> { + if (ZonedDateTime.parse(image.creationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME).isAfter(cutDate)) { + Iterator i = image.tags().iterator(); + Tag t; + String appEnvTag = null; + while (i.hasNext()) { + t = i.next(); + if (t.key().equals("application_environment")) { + appEnvTag = t.value(); + break; + } } + amiList.add(new AMI( + image.imageId(), + appEnvTag, + image.creationDate() + )); } - amiList.add(new AMI( - image.imageId(), - appEnvTag, - image.creationDate() - )); - } - }); - amiList.sort((a, b) -> - ZonedDateTime.parse(a.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME) - .compareTo(ZonedDateTime.parse(b.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME))); + }); + amiList.sort((a, b) -> - ZonedDateTime.parse(a.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME) + .compareTo(ZonedDateTime.parse(b.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME))); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "AMITagManager: could not retrieve AMI list", e); + throw e; } return amiList; } @@ -80,8 +87,14 @@ public void updateAmiTag(String amiId, String applicationEnvironment) { .resources(amiId) .tags(newAppEnv) .build(); - CreateTagsResponse resp = ec2Client.createTags(request); - if (!resp.sdkHttpResponse().isSuccessful()) - logger.severe("Tag update failed for " + amiId + " and application_environment tag = " + applicationEnvironment); + CreateTagsResponse resp; + try { + resp = ec2Client.createTags(request); + if (!resp.sdkHttpResponse().isSuccessful()) + throw AwsServiceException.builder().message("Http code \" + resp.sdkHttpResponse().statusCode() + \" received").build(); + } catch (Exception e) { + logger.severe("AMITagManager: tag update failed for " + amiId + " and application_environment tag = " + applicationEnvironment + ", " + e); + throw e; + } } } From dcf914984017ca435b284c6372147c76f355d601 Mon Sep 17 00:00:00 2001 From: brunoasr Date: Tue, 30 Jan 2024 01:06:33 -0300 Subject: [PATCH 04/10] Code optimization --- .../orion/core/actions/aws/AmiTagManager.java | 50 +++++++++++++------ .../com/pinterest/orion/server/api/AMI.java | 19 ++++++- .../orion/server/api/ClusterManagerApi.java | 10 ++-- .../resources/webapp/src/actions/cluster.js | 12 ++--- .../webapp/src/basic-components/AMI.js | 6 +-- .../main/resources/webapp/src/reducers/app.js | 4 +- .../main/resources/webapp/src/sagas/index.js | 8 +-- 7 files changed, 73 insertions(+), 36 deletions(-) diff --git a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java index 05cbacfa..cc01fd17 100644 --- a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java +++ b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java @@ -1,3 +1,18 @@ +/******************************************************************************* + * Copyright 2024 Pinterest, 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.pinterest.orion.core.actions.aws; import java.time.ZonedDateTime; @@ -8,8 +23,9 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.function.UnaryOperator; -import com.pinterest.orion.server.api.AMI; +import com.pinterest.orion.server.api.Ami; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.services.ec2.Ec2Client; @@ -23,27 +39,33 @@ public class AmiTagManager { private static final Logger logger = Logger.getLogger(AmiTagManager.class.getCanonicalName()); private Ec2Client ec2Client; + public static String KEY_APPLICATION = "application"; + public static String KEY_RELEASE = "release"; + public static String KEY_CPU_ARCHITECTURE = "cpu_architecture"; + public static String KEY_APPLICATION_ENVIRONMENT = "application_environment"; + public static String VALUE_KAFKA = "kafka"; + UnaryOperator tag = key -> "tag:" + key; public AmiTagManager() { ec2Client = Ec2Client.create(); } - public List getAmiList(Map filter) { - List amiList = new ArrayList<>(); + public List getAmiList(Map filter) { + List amiList = new ArrayList<>(); DescribeImagesRequest.Builder builder = DescribeImagesRequest.builder(); builder = builder.filters( - Filter.builder().name("tag:application").values("kafka").build() + Filter.builder().name(tag.apply(KEY_APPLICATION)).values(VALUE_KAFKA).build() ); - if (filter.containsKey("os")) + if (filter.containsKey(KEY_RELEASE)) builder = builder.filters( - Filter.builder().name("tag:release").values(filter.get("os")).build() + Filter.builder().name(tag.apply(KEY_RELEASE)).values(filter.get(KEY_RELEASE)).build() ); - if (filter.containsKey("arch")) + if (filter.containsKey(KEY_CPU_ARCHITECTURE)) builder = builder.filters( - Filter.builder().name("tag:cpu_architecture").values(filter.get("arch")).build() + Filter.builder().name(tag.apply(KEY_CPU_ARCHITECTURE)).values(filter.get(KEY_CPU_ARCHITECTURE)).build() ); builder = builder.filters( - Filter.builder().name("tag:application_environment").values("*").build() + Filter.builder().name(tag.apply(KEY_APPLICATION_ENVIRONMENT)).values("*").build() ); try { DescribeImagesResponse resp = ec2Client.describeImages(builder.build()); @@ -56,12 +78,12 @@ public List getAmiList(Map filter) { String appEnvTag = null; while (i.hasNext()) { t = i.next(); - if (t.key().equals("application_environment")) { + if (t.key().equals(KEY_APPLICATION_ENVIRONMENT)) { appEnvTag = t.value(); break; } } - amiList.add(new AMI( + amiList.add(new Ami( image.imageId(), appEnvTag, image.creationDate() @@ -72,7 +94,7 @@ public List getAmiList(Map filter) { .compareTo(ZonedDateTime.parse(b.getCreationDate(), DateTimeFormatter.ISO_ZONED_DATE_TIME))); } } catch (Exception e) { - logger.log(Level.SEVERE, "AMITagManager: could not retrieve AMI list", e); + logger.log(Level.SEVERE, "AmiTagManager: could not retrieve AMI list", e); throw e; } return amiList; @@ -81,7 +103,7 @@ public List getAmiList(Map filter) { public void updateAmiTag(String amiId, String applicationEnvironment) { CreateTagsRequest.Builder builder = CreateTagsRequest.builder(); Tag newAppEnv = Tag.builder() - .key("application_environment") + .key(KEY_APPLICATION_ENVIRONMENT) .value(applicationEnvironment).build(); CreateTagsRequest request = builder .resources(amiId) @@ -93,7 +115,7 @@ public void updateAmiTag(String amiId, String applicationEnvironment) { if (!resp.sdkHttpResponse().isSuccessful()) throw AwsServiceException.builder().message("Http code \" + resp.sdkHttpResponse().statusCode() + \" received").build(); } catch (Exception e) { - logger.severe("AMITagManager: tag update failed for " + amiId + " and application_environment tag = " + applicationEnvironment + ", " + e); + logger.severe("AmiTagManager: tag update failed for " + amiId + " and application_environment tag = " + applicationEnvironment + ", " + e); throw e; } } diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java index 06dc91a0..c8921070 100644 --- a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java @@ -1,11 +1,26 @@ +/******************************************************************************* + * Copyright 2024 Pinterest, 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.pinterest.orion.server.api; -public class AMI { +public class Ami { private final String amiId; private final String applicationEnvironment; private final String creationDate; - public AMI(String amiId, String applicationEnvironment, String creationDate) { + public Ami(String amiId, String applicationEnvironment, String creationDate) { this.amiId = amiId; this.applicationEnvironment = applicationEnvironment; this.creationDate = creationDate; diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java b/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java index 478f7ab0..5551d96e 100644 --- a/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java @@ -117,15 +117,15 @@ public Map> getUtilizationDetailsByCluster() { @Path("/describeImages") @GET - public List describeImages( - @QueryParam("os") String os, - @QueryParam("arch") String arch + public List describeImages( + @QueryParam("release") String os, + @QueryParam("cpu_architecture") String arch ) { Map filter = new HashMap<>(); if (os != null) - filter.put("os", os); + filter.put("release", os); if (arch != null) - filter.put("arch", arch); + filter.put("cpu_architecture", arch); if (amiTagManager == null) amiTagManager = new AmiTagManager(); return amiTagManager.getAmiList(filter); diff --git a/orion-server/src/main/resources/webapp/src/actions/cluster.js b/orion-server/src/main/resources/webapp/src/actions/cluster.js index 76d4c6e6..d06b64bf 100644 --- a/orion-server/src/main/resources/webapp/src/actions/cluster.js +++ b/orion-server/src/main/resources/webapp/src/actions/cluster.js @@ -30,9 +30,9 @@ export const UTILIZATION_REQUESTED = "UTILIZATION_REQUESTED"; export const UTILIZATION_RECEIVED = "UTILIZATION_RECEIVED"; export const COST_REQUESTED = "COST_REQUESTED"; export const COST_RECEIVED = "COST_RECEIVED"; -export const AMILIST_REQUESTED = "AMILIST_REQUESTED"; -export const AMILIST_RECEIVED = "AMILIST_RECEIVED"; -export const AMITAG_UPDATE = "AMITAG_UPDATE"; +export const AMI_LIST_REQUESTED = "AMI_LIST_REQUESTED"; +export const AMI_LIST_RECEIVED = "AMI_LIST_RECEIVED"; +export const AMI_TAG_UPDATE = "AMI_TAG_UPDATE"; export function requestCluster(clusterId) { return { type: CLUSTER_REQUESTED, payload: { clusterId } }; @@ -116,21 +116,21 @@ export function receiveClusterEndpoint(clusterId, field, data) { export function requestAmiList(filter) { return { - type: AMILIST_REQUESTED, + type: AMI_LIST_REQUESTED, payload: { filter }, }; } export function receiveAmiList(amiList) { return { - type: AMILIST_RECEIVED, + type: AMI_LIST_RECEIVED, payload: { amiList }, }; } export function updateAmiTag(amiId, applicationEnvironment) { return { - type: AMITAG_UPDATE, + type: AMI_TAG_UPDATE, payload: { amiId, applicationEnvironment }, }; } diff --git a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js index 2f4a305c..f6f6031c 100644 --- a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js +++ b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright 2020 Pinterest, Inc. + * Copyright 2024 Pinterest, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,9 +87,9 @@ function AMI({ amiList, requestAmiList, updateAmiTag }) { const applyFilter = () => { const parms = []; if (os) - parms.push("os=" + os); + parms.push("release=" + os); if (cpuArch) - parms.push("arch=" + cpuArch); + parms.push("cpu_architecture=" + cpuArch); requestAmiList(parms.join('&')); } diff --git a/orion-server/src/main/resources/webapp/src/reducers/app.js b/orion-server/src/main/resources/webapp/src/reducers/app.js index e8d8276e..8ca73629 100644 --- a/orion-server/src/main/resources/webapp/src/reducers/app.js +++ b/orion-server/src/main/resources/webapp/src/reducers/app.js @@ -22,7 +22,7 @@ import { AUTO_REFRESH_ENABLED, AUTO_REFRESH_DISABLED, } from "../actions/app"; -import { UTILIZATION_RECEIVED, COST_RECEIVED, AMILIST_RECEIVED } from "../actions/cluster"; +import { UTILIZATION_RECEIVED, COST_RECEIVED, AMI_LIST_RECEIVED } from "../actions/cluster"; export default function showError( state = { @@ -52,7 +52,7 @@ export default function showError( return { ...state, utilization: action.payload.utilization }; case COST_RECEIVED: return { ...state, cost: action.payload.cost }; - case AMILIST_RECEIVED: + case AMI_LIST_RECEIVED: return { ...state, amiList: action.payload.amiList }; default: return state; diff --git a/orion-server/src/main/resources/webapp/src/sagas/index.js b/orion-server/src/main/resources/webapp/src/sagas/index.js index af0d4992..e1b8445d 100644 --- a/orion-server/src/main/resources/webapp/src/sagas/index.js +++ b/orion-server/src/main/resources/webapp/src/sagas/index.js @@ -38,9 +38,9 @@ import { receiveUtilization, COST_REQUESTED, receiveCost, - AMILIST_REQUESTED, + AMI_LIST_REQUESTED, receiveAmiList, - AMITAG_UPDATE + AMI_TAG_UPDATE } from "../actions/cluster"; import { CLUSTERS_SUMMARY_REQUESTED, @@ -98,11 +98,11 @@ function* globalSensorWatcher() { } function* amiListWatcher() { - yield takeEvery(AMILIST_REQUESTED, fetchAmiList); + yield takeEvery(AMI_LIST_REQUESTED, fetchAmiList); } function* amiTagUpdateWatcher() { - yield takeEvery(AMITAG_UPDATE, fetchAmiTagUpdate); + yield takeEvery(AMI_TAG_UPDATE, fetchAmiTagUpdate); } function* fetchCost() { From bf337403d2293e4b373d9ec40b209927290d5237 Mon Sep 17 00:00:00 2001 From: brunoasr Date: Tue, 30 Jan 2024 01:17:24 -0300 Subject: [PATCH 05/10] Standardize Ami casing --- .../src/main/resources/webapp/src/basic-components/AMI.js | 4 ++-- .../main/resources/webapp/src/basic-components/Homepage.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js index f6f6031c..d92bcc35 100644 --- a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js +++ b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js @@ -41,7 +41,7 @@ const useStyles = makeStyles(theme => ({ }, })); -function AMI({ amiList, requestAmiList, updateAmiTag }) { +function Ami({ amiList, requestAmiList, updateAmiTag }) { const classes = useStyles(); const [os, setOS] = React.useState(); const handleOSChange = event => { @@ -266,4 +266,4 @@ function AMI({ amiList, requestAmiList, updateAmiTag }) { ); } -export default connect(mapState, mapDispatch)(AMI); +export default connect(mapState, mapDispatch)(Ami); diff --git a/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js b/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js index 6696bacb..34f8c844 100644 --- a/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js +++ b/orion-server/src/main/resources/webapp/src/basic-components/Homepage.js @@ -26,7 +26,7 @@ import { } from "@material-ui/core"; import Summary from "./Summary"; import Utilization from "./Utilization"; -import AMI from "./AMI"; +import Ami from "./Ami"; const routes = [ { @@ -41,7 +41,7 @@ const routes = [ }, { subpath: "ami", - component: AMI, + component: Ami, label: "AMI", }, ]; From 04b78a08c5b0a40d406901a660096a9e7b689687 Mon Sep 17 00:00:00 2001 From: brunoasr Date: Tue, 30 Jan 2024 10:37:45 -0300 Subject: [PATCH 06/10] Add javadoc --- .../orion/core/actions/aws/AmiTagManager.java | 17 +++++++++++++++++ .../com/pinterest/orion/server/api/AMI.java | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java index cc01fd17..45ceedd9 100644 --- a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java +++ b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java @@ -36,6 +36,11 @@ import software.amazon.awssdk.services.ec2.model.Filter; import software.amazon.awssdk.services.ec2.model.Tag; +/** + * AmiTagManager interfaces APIs in + * {@link com.pinterest.orion.server.api.ClusterManagerApi ClusterManagerApi} + * with AWS for AMI tag management. + */ public class AmiTagManager { private static final Logger logger = Logger.getLogger(AmiTagManager.class.getCanonicalName()); private Ec2Client ec2Client; @@ -50,6 +55,12 @@ public AmiTagManager() { ec2Client = Ec2Client.create(); } + /** + * retrieve AMI list from cloud provider + * + * @param filter - map of criteria fields + * @return list of Ami objects + */ public List getAmiList(Map filter) { List amiList = new ArrayList<>(); DescribeImagesRequest.Builder builder = DescribeImagesRequest.builder(); @@ -100,6 +111,12 @@ public List getAmiList(Map filter) { return amiList; } + /** + * update AMI tag 'application_environment' + * + * @param amiId - target AMI id + * @param applicationEnvironment - new tag value + */ public void updateAmiTag(String amiId, String applicationEnvironment) { CreateTagsRequest.Builder builder = CreateTagsRequest.builder(); Tag newAppEnv = Tag.builder() diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java index c8921070..6202d41b 100644 --- a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java @@ -15,6 +15,10 @@ *******************************************************************************/ package com.pinterest.orion.server.api; +/** + * Specialized object to store AMI information. + * Used to transmit a list of AMIs to the frontend. + */ public class Ami { private final String amiId; private final String applicationEnvironment; From b1da636d3fe13719b1b5655fc8b70d218f69151b Mon Sep 17 00:00:00 2001 From: brunoasr Date: Tue, 30 Jan 2024 10:59:36 -0300 Subject: [PATCH 07/10] More javadoc --- .../main/java/com/pinterest/orion/server/api/AMI.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java index 6202d41b..5e539029 100644 --- a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java @@ -24,6 +24,15 @@ public class Ami { private final String applicationEnvironment; private final String creationDate; + /** + * creates a new Ami instance + * + * @param amiId - for AWS, the string "ami-" and a sequence of 17 characters + * @param applicationEnvironment - comma-separated list of environments (dev, test, + * staging, prod) supported by this ami + * @param creationDate - ami creation date, UTC + * @return the new Ami instance + */ public Ami(String amiId, String applicationEnvironment, String creationDate) { this.amiId = amiId; this.applicationEnvironment = applicationEnvironment; From 729b5716ae4e02369d3418c80411bf745c20eaf7 Mon Sep 17 00:00:00 2001 From: brunoasr Date: Wed, 31 Jan 2024 12:35:41 -0300 Subject: [PATCH 08/10] Replace other fixed string instances --- .../orion/core/actions/aws/AmiTagManager.java | 14 ++++++++------ .../orion/server/api/ClusterManagerApi.java | 12 ++++++------ .../resources/webapp/src/basic-components/AMI.js | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java index 45ceedd9..9345a0a8 100644 --- a/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java +++ b/orion-server/src/main/java/com/pinterest/orion/core/actions/aws/AmiTagManager.java @@ -44,12 +44,14 @@ public class AmiTagManager { private static final Logger logger = Logger.getLogger(AmiTagManager.class.getCanonicalName()); private Ec2Client ec2Client; - public static String KEY_APPLICATION = "application"; - public static String KEY_RELEASE = "release"; - public static String KEY_CPU_ARCHITECTURE = "cpu_architecture"; - public static String KEY_APPLICATION_ENVIRONMENT = "application_environment"; - public static String VALUE_KAFKA = "kafka"; - UnaryOperator tag = key -> "tag:" + key; + public static final String KEY_IS_PUBLIC = "is-public"; + public static final String KEY_AMI_ID = "ami_id"; + public static final String KEY_APPLICATION = "application"; + public static final String KEY_RELEASE = "release"; + public static final String KEY_CPU_ARCHITECTURE = "cpu_architecture"; + public static final String KEY_APPLICATION_ENVIRONMENT = "application_environment"; + public static final String VALUE_KAFKA = "kafka"; + public static UnaryOperator tag = key -> "tag:" + key; public AmiTagManager() { ec2Client = Ec2Client.create(); diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java b/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java index 5551d96e..c80643f2 100644 --- a/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java +++ b/orion-server/src/main/java/com/pinterest/orion/server/api/ClusterManagerApi.java @@ -118,14 +118,14 @@ public Map> getUtilizationDetailsByCluster() { @Path("/describeImages") @GET public List describeImages( - @QueryParam("release") String os, - @QueryParam("cpu_architecture") String arch + @QueryParam(AmiTagManager.KEY_RELEASE) String os, + @QueryParam(AmiTagManager.KEY_CPU_ARCHITECTURE) String arch ) { Map filter = new HashMap<>(); if (os != null) - filter.put("release", os); + filter.put(AmiTagManager.KEY_RELEASE, os); if (arch != null) - filter.put("cpu_architecture", arch); + filter.put(AmiTagManager.KEY_CPU_ARCHITECTURE, arch); if (amiTagManager == null) amiTagManager = new AmiTagManager(); return amiTagManager.getAmiList(filter); @@ -134,8 +134,8 @@ public List describeImages( @Path("/updateImageTag") @PUT public void updateImageTag( - @QueryParam("ami_id") String amiId, - @QueryParam("application_environment") String applicationEnvironment + @QueryParam(AmiTagManager.KEY_AMI_ID) String amiId, + @QueryParam(AmiTagManager.KEY_APPLICATION_ENVIRONMENT) String applicationEnvironment ) { if (amiTagManager == null) amiTagManager = new AmiTagManager(); diff --git a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js index d92bcc35..99741d44 100644 --- a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js +++ b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js @@ -87,9 +87,9 @@ function Ami({ amiList, requestAmiList, updateAmiTag }) { const applyFilter = () => { const parms = []; if (os) - parms.push("release=" + os); + parms.push(AmiTagManager.KEY_RELEASE + "=" + os); if (cpuArch) - parms.push("cpu_architecture=" + cpuArch); + parms.push(AmiTagManager.KEY_CPU_ARCHITECTURE + "=" + cpuArch); requestAmiList(parms.join('&')); } From 5511e30856e92073ee154b651a4a5e3828383f5a Mon Sep 17 00:00:00 2001 From: brunoasr Date: Wed, 31 Jan 2024 12:57:34 -0300 Subject: [PATCH 09/10] Revert some replacements --- .../src/main/resources/webapp/src/basic-components/AMI.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js index 99741d44..d92bcc35 100644 --- a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js +++ b/orion-server/src/main/resources/webapp/src/basic-components/AMI.js @@ -87,9 +87,9 @@ function Ami({ amiList, requestAmiList, updateAmiTag }) { const applyFilter = () => { const parms = []; if (os) - parms.push(AmiTagManager.KEY_RELEASE + "=" + os); + parms.push("release=" + os); if (cpuArch) - parms.push(AmiTagManager.KEY_CPU_ARCHITECTURE + "=" + cpuArch); + parms.push("cpu_architecture=" + cpuArch); requestAmiList(parms.join('&')); } From f0595445aa39a5bb040988cb16972057e2109c5f Mon Sep 17 00:00:00 2001 From: brunoasr Date: Thu, 1 Feb 2024 15:52:02 -0300 Subject: [PATCH 10/10] Rename files --- .../java/com/pinterest/orion/server/api/{AMI.java => Ami.java} | 0 .../main/resources/webapp/src/basic-components/{AMI.js => Ami.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename orion-server/src/main/java/com/pinterest/orion/server/api/{AMI.java => Ami.java} (100%) rename orion-server/src/main/resources/webapp/src/basic-components/{AMI.js => Ami.js} (100%) diff --git a/orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java b/orion-server/src/main/java/com/pinterest/orion/server/api/Ami.java similarity index 100% rename from orion-server/src/main/java/com/pinterest/orion/server/api/AMI.java rename to orion-server/src/main/java/com/pinterest/orion/server/api/Ami.java diff --git a/orion-server/src/main/resources/webapp/src/basic-components/AMI.js b/orion-server/src/main/resources/webapp/src/basic-components/Ami.js similarity index 100% rename from orion-server/src/main/resources/webapp/src/basic-components/AMI.js rename to orion-server/src/main/resources/webapp/src/basic-components/Ami.js