commit 050bb67c08f3ef98ef8211a4570e440f55f28a51 Author: Eric Yang Date: Mon Oct 23 19:50:49 2017 -0400 YARN-7193. Added REST API for catalog YARN applications. diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/webapp/ApiServer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/webapp/ApiServer.java index 5d1ada5..b93f9e6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/webapp/ApiServer.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/main/java/org/apache/hadoop/yarn/service/webapp/ApiServer.java @@ -25,6 +25,7 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException; import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.service.api.records.AppCatalogEntry; import org.apache.hadoop.yarn.service.api.records.Component; import org.apache.hadoop.yarn.service.api.records.Service; import org.apache.hadoop.yarn.service.api.records.ServiceState; @@ -43,6 +44,7 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -400,4 +402,87 @@ public Response updateServiceSpec(@PathParam(SERVICE_NAME) } } + /** + * Register application in application catalog. + * + * @param app - An application store entry + * @return web status code + */ + @POST + @Path(APP_REGISTER_PATH) + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response registerApps(AppCatalogEntry app) { + try { + if(app.getName()== null) { + throw new IllegalArgumentException("Application name can not be null."); + } + if(app.getOrg()== null) { + throw new IllegalArgumentException("Application organization " + + "can not be null."); + } + SERVICE_CLIENT.register(app); + } catch (IOException e) { + ServiceStatus serviceStatus = new ServiceStatus(); + serviceStatus + .setDiagnostics("Failed to register application:" + e.getMessage()); + return Response.status(Status.SERVICE_UNAVAILABLE) + .entity(serviceStatus).build(); + } catch (IllegalArgumentException e) { + ServiceStatus serviceStatus = new ServiceStatus(); + serviceStatus + .setDiagnostics("Failed to register application:" + e.getMessage()); + return Response.status(Status.BAD_REQUEST) + .entity(serviceStatus).build(); + } + return Response.status(Status.ACCEPTED).build(); + } + + /** + * Search for qpplication in application catalog. + * + * @param query - User input string + * @return a list of applications matching user query + */ + @POST + @Path(APP_SEARCH_PATH) + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response searchApps(@QueryParam("q") String query) { + List list; + try { + list = SERVICE_CLIENT.search(query); + } catch (IOException e) { + ServiceStatus serviceStatus = new ServiceStatus(); + serviceStatus + .setDiagnostics("Failed to search application:" + e.getMessage()); + return Response.status(Status.SERVICE_UNAVAILABLE) + .entity(serviceStatus).build(); + } + return Response.status(Status.OK).entity(list).build(); + } + + /** + * Recommend for applications from application catalog. + * + * @return a list of recommended applications + */ + @GET + @Path(APP_RECOMMEND_PATH) + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response getRecommendApps() { + List list; + try { + list = SERVICE_CLIENT.getRecommended(); + } catch (IOException e) { + ServiceStatus serviceStatus = new ServiceStatus(); + serviceStatus + .setDiagnostics("Failed to get recommended applications:" + + e.getMessage()); + return Response.status(Status.SERVICE_UNAVAILABLE) + .entity(serviceStatus).build(); + } + return Response.status(Status.OK).entity(list).build(); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiServer.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiServer.java index 798519c..026e8e4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiServer.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiServer.java @@ -19,6 +19,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.service.api.records.AppCatalogEntry; import org.apache.hadoop.yarn.service.api.records.Artifact; import org.apache.hadoop.yarn.service.api.records.Artifact.TypeEnum; import org.apache.hadoop.yarn.service.api.records.Component; @@ -521,4 +522,52 @@ public void testGetServicesList() { .build().getStatus(), actual.getStatus()); } + + /** + * Test register application when solr is disabled. + */ + @Test + public void testRegisterApp() { + // Test invalid input + AppCatalogEntry app = new AppCatalogEntry(); + final Response actual = apiServer.registerApps(app); + assertEquals("api is unavailable", + Response.status(Status.BAD_REQUEST) + .build().getStatus(), + actual.getStatus()); + // Test for service unavailability + app.setOrg("jenkins-ci.org"); + app.setName("jenkins"); + final Response actual2 = apiServer.registerApps(app); + assertEquals("api is unavailable", + Response.status(Status.SERVICE_UNAVAILABLE) + .build().getStatus(), + actual2.getStatus()); + } + + /** + * Test search for application when solr is disabled. + */ + @Test + public void testSearchApp() { + String query = "nothing"; + final Response actual = apiServer.searchApps(query); + assertEquals("api is unavailable", + Response.status(Status.SERVICE_UNAVAILABLE) + .build().getStatus(), + actual.getStatus()); + } + + /** + * Test fetching recommended application when + * solr is disabled. + */ + @Test + public void testRecommendedApp() { + final Response actual = apiServer.getRecommendApps(); + assertEquals("api is unavailable", + Response.status(Status.SERVICE_UNAVAILABLE) + .build().getStatus(), + actual.getStatus()); + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiService.java index 8b51eef..6fcc476 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services-api/src/test/java/org/apache/hadoop/yarn/service/TestApiService.java @@ -18,6 +18,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.service.api.records.AppCatalogEntry; import org.apache.hadoop.yarn.service.api.records.Component; import org.apache.hadoop.yarn.service.api.records.Service; import org.apache.hadoop.yarn.service.webapp.ApiServer; @@ -55,6 +56,21 @@ public static void setupBeforeClass() throws Exception { setupApiServer(); } + /** + * Create a copy of ApiServer and stub the ServiceClient + * with YarnSolrClientTest. This helps to test ServiceClient + * against embedded solr server. + * + * @return + * @throws Exception + */ + private static void setupApiServer() throws Exception { + setupServiceClient(); + if (apiServer == null) { + apiServer = new ApiServer(client); + } + } + @AfterClass public static void tearDownAfterClass() throws IOException { shutdown(); @@ -125,18 +141,49 @@ public void testUpdateServiceSpec() { } /** - * Create a copy of ApiServer and stub the ServiceClient - * with YarnSolrClientTest. This helps to test ServiceClient - * against embedded solr server. - * - * @return - * @throws Exception + * Test register application when solr is enabled. */ - private static void setupApiServer() throws Exception { - setupServiceClient(); - if (apiServer == null) { - apiServer = new ApiServer(client); - } + @Test + public void testRegisterApp() { + Service service = new Service(); + service.setName("jenkins"); + service.addComponent(createComponent("compa", 1, "sleep 1000")); + AppCatalogEntry app = new AppCatalogEntry(); + app.setOrg("jenkins-ci.org"); + app.setName("jenkins"); + app.setDesc("Most popular open source automation tool."); + app.setApp(service); + final Response actual = apiServer.registerApps(app); + assertEquals("register api should return OK: ", + Response.status(Status.ACCEPTED) + .build().getStatus(), + actual.getStatus()); + } + + /** + * Test search for application when solr is enabled. + */ + @Test + public void testSearchApp() { + String query = "id:*"; + final Response actual = apiServer.searchApps(query); + assertEquals("search api should return OK: ", + Response.status(Status.OK) + .build().getStatus(), + actual.getStatus()); + } + + /** + * Test fetching recommended application when + * solr is enabled. + */ + @Test + public void testRecommendedApp() { + final Response actual = apiServer.getRecommendApps(); + assertEquals("recommend api should return OK: ", + Response.status(Status.OK) + .build().getStatus(), + actual.getStatus()); } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/AppCatalogEntry.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/AppCatalogEntry.java new file mode 100644 index 0000000..61e5282 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/api/records/AppCatalogEntry.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.hadoop.yarn.service.api.records; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Data model for registering an application in application catalog. + * + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) +public class AppCatalogEntry { + private String id; + private String org; + private String name; + private String desc; + private String icon = "css/img/feather.png"; + private long like; + private long download; + private Service app; + + public String getOrg() { + return org; + } + + public void setOrg(String org) { + this.org = org; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public long getLike() { + return like; + } + + public void setLike(long like) { + this.like = like; + } + + public long getDownload() { + return download; + } + + public void setDownload(long download) { + this.download = download; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Service getApp() { + return app; + } + + public void setApp(Service app) { + this.app = app; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + +} \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java index d4806c5..f4c7110 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/ServiceClient.java @@ -68,6 +68,7 @@ import org.apache.hadoop.yarn.proto.ClientAMProtocol.StopRequestProto; import org.apache.hadoop.yarn.service.ClientAMProtocol; import org.apache.hadoop.yarn.service.ServiceMaster; +import org.apache.hadoop.yarn.service.api.records.AppCatalogEntry; import org.apache.hadoop.yarn.service.api.records.Component; import org.apache.hadoop.yarn.service.api.records.Service; import org.apache.hadoop.yarn.service.api.records.ServiceState; @@ -1071,4 +1072,49 @@ public Service updateSpec(String serviceName, Service service) persistAppDef(appDir, service); return service; } + + /** + * Register YARN application in application catalog. + * + * @param app + * @throws IOException - if solr is not enabled. + */ + public void register(AppCatalogEntry app) throws IOException, + IllegalArgumentException { + ServiceApiUtil.validateNameFormat(app.getName(), getConfig()); + if(ysc.isEnabled()) { + ysc.register(app); + } else { + throw new IOException("Operation is not supported."); + } + } + + /** + * Search YARN application in application catalog. + * + * @param keyword + * @return + * @throws IOException - if solr is not enabled. + */ + public List search(String keyword) throws IOException { + if(ysc.isEnabled()) { + return ysc.search(keyword); + } else { + throw new IOException("Operation is not supported."); + } + } + + /** + * Retrieve recommended applications from application catalog. + * + * @return + * @throws IOException - if solr is not enabled. + */ + public List getRecommended() throws IOException { + if(ysc.isEnabled()) { + return ysc.getRecommendedApps(); + } else { + throw new IOException("Operation is not supported."); + } + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/YarnSolrClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/YarnSolrClient.java index e0a3e8b..db66100 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/YarnSolrClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/client/YarnSolrClient.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Random; import javax.naming.ServiceUnavailableException; @@ -45,7 +46,9 @@ import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException; +import org.apache.hadoop.yarn.service.api.records.AppCatalogEntry; import org.apache.hadoop.yarn.service.api.records.Service; +import org.apache.hadoop.yarn.service.utils.RandomWord; import static org.apache.hadoop.yarn.conf.YarnConfiguration.*; @@ -161,14 +164,49 @@ public Service findAppEntry(String appName, String username) throws public Service deployApp(Service yarnApp, String username) throws ServiceUnavailableException { check(); + long download = 0; SolrClient solr = getSolrClient(); Collection docs = new HashSet(); ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - + // Find application information from AppCatalog try { + String name; + try { + Random r = new Random(); + int low = 17; + int high = RandomWord.MAX; + int seed = r.nextInt(high - low) + low; + int seed2 = r.nextInt(high - low) + low; + name = RandomWord.getNewWord(seed).toLowerCase() + "-" + + RandomWord.getNewWord(seed2).toLowerCase(); + } catch (IllegalArgumentException e) { + name = "c" + java.util.UUID.randomUUID().toString().substring(0, 11); + } + SolrQuery query = new SolrQuery(); + query.setQuery("id:" + name); + query.setFilterQueries("type_s:AppCatalogEntry"); + query.setRows(1); + QueryResponse response = solr.query(query); + Iterator appList = response.getResults().listIterator(); + AppCatalogEntry entry = new AppCatalogEntry(); + while (appList.hasNext()) { + SolrDocument d = appList.next(); + entry.setOrg(d.get("org_s").toString()); + entry.setName(d.get("name_s").toString()); + entry.setDesc(d.get("desc_s").toString()); + yarnApp = mapper.readValue(d.get("yarnfile_s").toString(), + org.apache.hadoop.yarn.service.api.records.Service.class); + entry.setLike(Integer.parseInt(d.get("like_i").toString())); + entry.setDownload(Integer.parseInt(d.get("download_i").toString())); + download = entry.getDownload() + 1; + + // Update download count + docs.add(incrementDownload(d, download)); + } + if (yarnApp!=null) { // Register deployed application instance with AppList SolrInputDocument request = new SolrInputDocument(); @@ -327,6 +365,7 @@ public boolean isEnabled() { /** * Check if YARN Solr Integration is enabled. + * * @throws ServiceUnavailableException */ public void check() throws ServiceUnavailableException { @@ -335,4 +374,147 @@ public void check() throws ServiceUnavailableException { "support is unavailable."); } } + + /** + * Increment download number for deployed app. + * + * @param doc + * @param download + * @return + */ + private SolrInputDocument incrementDownload(SolrDocument doc, long download) { + Collection names = doc.getFieldNames(); + SolrInputDocument s = new SolrInputDocument(); + for (String name : names) { + if (!name.equals("_version_")) { + s.addField(name, doc.getFieldValues(name)); + } + } + download++; + s.setField("download_i", download); + return s; + } + + /** + * Register YARN application in application catalog. + * + * @param app + * @throws IOException + */ + public void register(AppCatalogEntry app) throws IOException { + Collection docs = new HashSet(); + SolrClient solr = getSolrClient(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + try { + SolrInputDocument buffer = new SolrInputDocument(); + buffer.setField("id", + java.util.UUID.randomUUID().toString().substring(0, 11)); + buffer.setField("org_s", app.getOrg()); + buffer.setField("name_s", app.getName()); + buffer.setField("desc_s", app.getDesc()); + if (app.getIcon() != null) { + buffer.setField("icon_s", app.getIcon()); + } + buffer.setField("type_s", "AppCatalogEntry"); + buffer.setField("like_i", 0); + buffer.setField("download_i", 0); + + // Keep only YARN data model for yarnfile field + String yarnFile = mapper.writeValueAsString(app); + LOG.info("app:" + yarnFile); + org.apache.hadoop.yarn.service.api.records.Service yarnApp = mapper + .readValue(yarnFile, + org.apache.hadoop.yarn.service.api.records.Service.class); + buffer.setField("yarnfile_s", mapper.writeValueAsString(yarnApp)); + + docs.add(buffer); + // Commit Solr changes. + UpdateResponse detailsResponse = solr.add(docs); + if (detailsResponse.getStatus() != 0) { + throw new IOException( + "Unable to register application in Application Catalog."); + } + solr.commit(); + } catch (SolrServerException | IOException e) { + throw new IOException( + "Unable to register application in Application Catalog. " + + e.getMessage()); + } + } + + /** + * Serach for YARN application in application catalog. + * + * @param keyword + * @return + */ + public List search(String keyword) { + List apps = new ArrayList(); + SolrClient solr = getSolrClient(); + SolrQuery query = new SolrQuery(); + if (keyword.length() == 0) { + query.setQuery("*:*"); + query.setFilterQueries("type_s:AppCatalogEntry"); + } else { + query.setQuery(keyword); + query.setFilterQueries("type_s:AppCatalogEntry"); + } + query.setRows(40); + QueryResponse response; + try { + response = solr.query(query); + Iterator list = response.getResults().listIterator(); + while (list.hasNext()) { + SolrDocument d = list.next(); + AppCatalogEntry entry = new AppCatalogEntry(); + entry.setId(d.get("id").toString()); + entry.setOrg(d.get("org_s").toString()); + entry.setName(d.get("name_s").toString()); + entry.setDesc(d.get("desc_s").toString()); + entry.setLike(Integer.parseInt(d.get("like_i").toString())); + entry.setDownload(Integer.parseInt(d.get("download_i").toString())); + apps.add(entry); + } + } catch (SolrServerException | IOException e) { + LOG.error("Error in searching for applications: ", e); + } + return apps; + } + + /** + * Return a list of recommended applications. + * + * @return + */ + public List getRecommendedApps() { + List apps = new ArrayList(); + SolrClient solr = getSolrClient(); + SolrQuery query = new SolrQuery(); + query.setQuery("*:*"); + query.setFilterQueries("type_s:AppCatalogEntry"); + query.setRows(40); + QueryResponse response; + try { + response = solr.query(query); + Iterator list = response.getResults().listIterator(); + while (list.hasNext()) { + SolrDocument d = list.next(); + AppCatalogEntry entry = new AppCatalogEntry(); + entry.setId(d.get("id").toString()); + entry.setOrg(d.get("org_s").toString()); + entry.setName(d.get("name_s").toString()); + entry.setDesc(d.get("desc_s").toString()); + if (d.get("icon_s") != null) { + entry.setIcon(d.get("icon_s").toString()); + } + entry.setLike(Integer.parseInt(d.get("like_i").toString())); + entry.setDownload(Integer.parseInt(d.get("download_i").toString())); + apps.add(entry); + } + } catch (SolrServerException | IOException e) { + LOG.error("Error getting a list of recommended applications: ", e); + } + return apps; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/RestApiConstants.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/RestApiConstants.java index b131f60..5f7af76 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/RestApiConstants.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/conf/RestApiConstants.java @@ -28,6 +28,10 @@ String SERVICE_STATE_PATH = "/services/{service_name}/state"; String COMPONENT_PATH = "/services/{service_name}/components/{component_name}"; + String APP_REGISTER_PATH = "/apps/register"; + String APP_SEARCH_PATH = "/apps/search"; + String APP_RECOMMEND_PATH = "/apps/recommend"; + // Query param String SERVICE_NAME = "service_name"; String COMPONENT_NAME = "component_name"; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/RandomWord.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/RandomWord.java new file mode 100644 index 0000000..eef9484 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/utils/RandomWord.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.hadoop.yarn.service.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; + +import com.nimbusds.jose.util.StandardCharset; + +/** + * Utility class to randomly generate English positive word. + * + */ +public class RandomWord { + + public static final int MAX = 2021; + protected RandomWord() { + } + + public static String getNewWord(int index) throws IllegalArgumentException { + if (index < 17) { + index = 17; + } else if (index > MAX) { + index = MAX; + } + int current = 0; + BufferedReader in = new BufferedReader(new InputStreamReader( + RandomWord.class.getResourceAsStream("/positive-words.txt"), + StandardCharset.UTF_8)); + String word = ""; + try { + while ((word = in.readLine()) != null) { + if (current > index) { + break; + } + current++; + } + in.close(); + } catch (IOException e) { + throw new IllegalArgumentException("File out of range."); + } + return word; + } + +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/resources/positive-words.txt b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/resources/positive-words.txt new file mode 100644 index 0000000..1386934 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/resources/positive-words.txt @@ -0,0 +1,2021 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +abound +abounds +abundance +abundant +accessable +accessible +acclaim +acclaimed +acclamation +accolade +accolades +accommodative +accomodative +accomplish +accomplished +accomplishment +accomplishments +accurate +accurately +achievable +achievement +achievements +achievible +acumen +adaptable +adaptive +adequate +adjustable +admirable +admirably +admiration +admire +admirer +admiring +admiringly +adorable +adore +adored +adorer +adoring +adoringly +adroit +adroitly +adulate +adulation +adulatory +advanced +advantage +advantageous +advantageously +advantages +adventuresome +adventurous +advocate +advocated +advocates +affability +affable +affably +affectation +affection +affectionate +affinity +affirm +affirmation +affirmative +affluence +affluent +afford +affordable +affordably +afordable +agile +agilely +agility +agreeable +agreeableness +agreeably +all-around +alluring +alluringly +altruistic +altruistically +amaze +amazed +amazement +amazes +amazing +amazingly +ambitious +ambitiously +ameliorate +amenable +amenity +amiability +amiabily +amiable +amicability +amicable +amicably +amity +ample +amply +amuse +amusing +amusingly +angel +angelic +apotheosis +appeal +appealing +applaud +appreciable +appreciate +appreciated +appreciates +appreciative +appreciatively +appropriate +approval +approve +ardent +ardently +ardor +articulate +aspiration +aspirations +aspire +assurance +assurances +assure +assuredly +assuring +astonish +astonished +astonishing +astonishingly +astonishment +astound +astounded +astounding +astoundingly +astutely +attentive +attraction +attractive +attractively +attune +audible +audibly +auspicious +authentic +authoritative +autonomous +available +aver +avid +avidly +award +awarded +awards +awe +awed +awesome +awesomely +awesomeness +awestruck +awsome +backbone +balanced +bargain +beauteous +beautiful +beautifullly +beautifully +beautify +beauty +beckon +beckoned +beckoning +beckons +believable +believeable +beloved +benefactor +beneficent +beneficial +beneficially +beneficiary +benefit +benefits +benevolence +benevolent +benifits +best +best-known +best-performing +best-selling +better +better-known +better-than-expected +beutifully +blameless +bless +blessing +bliss +blissful +blissfully +blithe +blockbuster +bloom +blossom +bolster +bonny +bonus +bonuses +boom +booming +boost +boundless +bountiful +brainiest +brainy +brand-new +brave +bravery +bravo +breakthrough +breakthroughs +breathlessness +breathtaking +breathtakingly +breeze +bright +brighten +brighter +brightest +brilliance +brilliances +brilliant +brilliantly +brisk +brotherly +bullish +buoyant +cajole +calm +calming +calmness +capability +capable +capably +captivate +captivating +carefree +cashback +cashbacks +catchy +celebrate +celebrated +celebration +celebratory +champ +champion +charisma +charismatic +charitable +charm +charming +charmingly +chaste +cheaper +cheapest +cheer +cheerful +cheery +cherish +cherished +cherub +chic +chivalrous +chivalry +civility +civilize +clarity +classic +classy +clean +cleaner +cleanest +cleanliness +cleanly +clear +clear-cut +cleared +clearer +clearly +clears +clever +cleverly +cohere +coherence +coherent +cohesive +colorful +comely +comfort +comfortable +comfortably +comforting +comfy +commend +commendable +commendably +commitment +commodious +compact +compactly +compassion +compassionate +compatible +competitive +complement +complementary +complemented +complements +compliant +compliment +complimentary +comprehensive +conciliate +conciliatory +concise +confidence +confident +congenial +congratulate +congratulation +congratulations +congratulatory +conscientious +considerate +consistent +consistently +constructive +consummate +contentment +continuity +contrasty +contribution +convenience +convenient +conveniently +convience +convienient +convient +convincing +convincingly +cool +coolest +cooperative +cooperatively +cornerstone +correct +correctly +cost-effective +cost-saving +counter-attack +counter-attacks +courage +courageous +courageously +courageousness +courteous +courtly +covenant +cozy +creative +credence +credible +crisp +crisper +cure +cure-all +cushy +cute +cuteness +danke +danken +daring +daringly +darling +dashing +dauntless +dawn +dazzle +dazzled +dazzling +dead-cheap +dead-on +decency +decent +decisive +decisiveness +dedicated +defeat +defeated +defeating +defeats +defender +deference +deft +deginified +delectable +delicacy +delicate +delicious +delight +delighted +delightful +delightfully +delightfulness +dependable +dependably +deservedly +deserving +desirable +desiring +desirous +destiny +detachable +devout +dexterous +dexterously +dextrous +dignified +dignify +dignity +diligence +diligent +diligently +diplomatic +dirt-cheap +distinction +distinctive +distinguished +diversified +divine +divinely +dominate +dominated +dominates +dote +dotingly +doubtless +dreamland +dumbfounded +dumbfounding +dummy-proof +durable +dynamic +eager +eagerly +eagerness +earnest +earnestly +earnestness +ease +eased +eases +easier +easiest +easiness +easing +easy +easy-to-use +easygoing +ebullience +ebullient +ebulliently +ecenomical +economical +ecstasies +ecstasy +ecstatic +ecstatically +edify +educated +effective +effectively +effectiveness +effectual +efficacious +efficient +efficiently +effortless +effortlessly +effusion +effusive +effusively +effusiveness +elan +elate +elated +elatedly +elation +electrify +elegance +elegant +elegantly +elevate +elite +eloquence +eloquent +eloquently +embolden +eminence +eminent +empathize +empathy +empower +empowerment +enchant +enchanted +enchanting +enchantingly +encourage +encouragement +encouraging +encouragingly +endear +endearing +endorse +endorsed +endorsement +endorses +endorsing +energetic +energize +energy-efficient +energy-saving +engaging +engrossing +enhance +enhanced +enhancement +enhances +enjoy +enjoyable +enjoyably +enjoyed +enjoying +enjoyment +enjoys +enlighten +enlightenment +enliven +ennoble +enough +enrapt +enrapture +enraptured +enrich +enrichment +enterprising +entertain +entertaining +entertains +enthral +enthrall +enthralled +enthuse +enthusiasm +enthusiast +enthusiastic +enthusiastically +entice +enticed +enticing +enticingly +entranced +entrancing +entrust +enviable +enviably +envious +enviously +enviousness +envy +equitable +ergonomical +err-free +erudite +ethical +eulogize +euphoria +euphoric +euphorically +evaluative +evenly +eventful +everlasting +evocative +exalt +exaltation +exalted +exaltedly +exalting +exaltingly +examplar +examplary +excallent +exceed +exceeded +exceeding +exceedingly +exceeds +excel +exceled +excelent +excellant +excelled +excellence +excellency +excellent +excellently +excels +exceptional +exceptionally +excite +excited +excitedly +excitedness +excitement +excites +exciting +excitingly +exellent +exemplar +exemplary +exhilarate +exhilarating +exhilaratingly +exhilaration +exonerate +expansive +expeditiously +expertly +exquisite +exquisitely +extol +extoll +extraordinarily +extraordinary +exuberance +exuberant +exuberantly +exult +exultant +exultation +exultingly +eye-catch +eye-catching +eyecatch +eyecatching +fabulous +fabulously +facilitate +fair +fairly +fairness +faith +faithful +faithfully +faithfulness +fame +famed +famous +famously +fancier +fancinating +fancy +fanfare +fans +fantastic +fantastically +fascinate +fascinating +fascinatingly +fascination +fashionable +fashionably +fast +fast-growing +fast-paced +faster +fastest +fastest-growing +faultless +fav +fave +favor +favorable +favored +favorite +favorited +favour +fearless +fearlessly +feasible +feasibly +feat +feature-rich +fecilitous +feisty +felicitate +felicitous +felicity +fertile +fervent +fervently +fervid +fervidly +fervor +festive +fidelity +fiery +fine +fine-looking +finely +finer +finest +firmer +first-class +first-in-class +first-rate +flashy +flatter +flattering +flatteringly +flawless +flawlessly +flexibility +flexible +flourish +flourishing +fluent +flutter +fond +fondly +fondness +foolproof +foremost +foresight +formidable +fortitude +fortuitous +fortuitously +fortunate +fortunately +fortune +fragrant +free +freed +freedom +freedoms +fresh +fresher +freshest +friendliness +friendly +frolic +frugal +fruitful +ftw +fulfillment +fun +futurestic +futuristic +gaiety +gaily +gain +gained +gainful +gainfully +gaining +gains +gallant +gallantly +galore +geekier +geeky +gem +gems +generosity +generous +generously +genial +genius +gentle +gentlest +genuine +gifted +glad +gladden +gladly +gladness +glamorous +glee +gleeful +gleefully +glimmer +glimmering +glisten +glistening +glitter +glitz +glorify +glorious +gloriously +glory +glow +glowing +glowingly +god-given +god-send +godlike +godsend +gold +golden +good +goodly +goodness +goodwill +goood +gooood +gorgeous +gorgeously +grace +graceful +gracefully +gracious +graciously +graciousness +grand +grandeur +grateful +gratefully +gratification +gratified +gratifies +gratify +gratifying +gratifyingly +gratitude +great +greatest +greatness +grin +groundbreaking +guarantee +guidance +guiltless +gumption +gush +gusto +gutsy +hail +halcyon +hale +hallmark +hallmarks +hallowed +handier +handily +hands-down +handsome +handsomely +handy +happier +happily +happiness +happy +hard-working +hardier +hardy +harmless +harmonious +harmoniously +harmonize +harmony +headway +heal +healthful +healthy +hearten +heartening +heartfelt +heartily +heartwarming +heaven +heavenly +helped +helpful +helping +hero +heroic +heroically +heroine +heroize +heros +high-quality +high-spirited +hilarious +holy +homage +honest +honesty +honor +honorable +honored +honoring +hooray +hopeful +hospitable +hot +hotcake +hotcakes +hottest +hug +humane +humble +humility +humor +humorous +humorously +humour +humourous +ideal +idealize +ideally +idol +idolize +idolized +idyllic +illuminate +illuminati +illuminating +illumine +illustrious +ilu +imaculate +imaginative +immaculate +immaculately +immense +impartial +impartiality +impartially +impassioned +impeccable +impeccably +important +impress +impressed +impresses +impressive +impressively +impressiveness +improve +improved +improvement +improvements +improves +improving +incredible +incredibly +indebted +individualized +indulgence +indulgent +industrious +inestimable +inestimably +inexpensive +infallibility +infallible +infallibly +influential +ingenious +ingeniously +ingenuity +ingenuous +ingenuously +innocuous +innovation +innovative +inpressed +insightful +insightfully +inspiration +inspirational +inspire +inspiring +instantly +instructive +instrumental +integral +integrated +intelligence +intelligent +intelligible +interesting +interests +intimacy +intimate +intricate +intrigue +intriguing +intriguingly +intuitive +invaluable +invaluablely +inventive +invigorate +invigorating +invincibility +invincible +inviolable +inviolate +invulnerable +irreplaceable +irreproachable +irresistible +irresistibly +issue-free +jaw-droping +jaw-dropping +jollify +jolly +jovial +joy +joyful +joyfully +joyous +joyously +jubilant +jubilantly +jubilate +jubilation +jubiliant +judicious +justly +keen +keenly +keenness +kid-friendly +kindliness +kindly +kindness +knowledgeable +kudos +large-capacity +laud +laudable +laudably +lavish +lavishly +law-abiding +lawful +lawfully +lead +leading +leads +lean +led +legendary +leverage +levity +liberate +liberation +liberty +lifesaver +light-hearted +lighter +likable +like +liked +likes +liking +lionhearted +lively +logical +long-lasting +lovable +lovably +love +loved +loveliness +lovely +lover +loves +loving +low-cost +low-price +low-priced +low-risk +lower-priced +loyal +loyalty +lucid +lucidly +luck +luckier +luckiest +luckiness +lucky +lucrative +luminous +lush +luster +lustrous +luxuriant +luxuriate +luxurious +luxuriously +luxury +lyrical +magic +magical +magnanimous +magnanimously +magnificence +magnificent +magnificently +majestic +majesty +manageable +maneuverable +marvel +marveled +marvelled +marvellous +marvelous +marvelously +marvelousness +marvels +master +masterful +masterfully +masterpiece +masterpieces +masters +mastery +matchless +mature +maturely +maturity +meaningful +memorable +merciful +mercifully +mercy +merit +meritorious +merrily +merriment +merriness +merry +mesmerize +mesmerized +mesmerizes +mesmerizing +mesmerizingly +meticulous +meticulously +mightily +mighty +mind-blowing +miracle +miracles +miraculous +miraculously +miraculousness +modern +modest +modesty +momentous +monumental +monumentally +morality +motivated +multi-purpose +navigable +neat +neatest +neatly +nice +nicely +nicer +nicest +nifty +nimble +noble +nobly +noiseless +non-violence +non-violent +notably +noteworthy +nourish +nourishing +nourishment +novelty +nurturing +oasis +obsession +obsessions +obtainable +openly +openness +optimal +optimism +optimistic +opulent +orderly +originality +outdo +outdone +outperform +outperformed +outperforming +outperforms +outshine +outshone +outsmart +outstanding +outstandingly +outstrip +outwit +ovation +overjoyed +overtake +overtaken +overtakes +overtaking +overtook +overture +pain-free +painless +painlessly +palatial +pamper +pampered +pamperedly +pamperedness +pampers +panoramic +paradise +paramount +pardon +passion +passionate +passionately +patience +patient +patiently +patriot +patriotic +peace +peaceable +peaceful +peacefully +peacekeepers +peach +peerless +pep +pepped +pepping +peppy +peps +perfect +perfection +perfectly +permissible +perseverance +persevere +personages +personalized +phenomenal +phenomenally +picturesque +piety +pinnacle +playful +playfully +pleasant +pleasantly +pleased +pleases +pleasing +pleasingly +pleasurable +pleasurably +pleasure +plentiful +pluses +plush +plusses +poetic +poeticize +poignant +poise +poised +polished +polite +politeness +popular +portable +posh +positive +positively +positives +powerful +powerfully +praise +praiseworthy +praising +pre-eminent +precious +precise +precisely +preeminent +prefer +preferable +preferably +prefered +preferes +preferring +prefers +premier +prestige +prestigious +prettily +pretty +priceless +pride +principled +privilege +privileged +prize +proactive +problem-free +problem-solver +prodigious +prodigiously +prodigy +productive +productively +proficient +proficiently +profound +profoundly +profuse +profusion +progress +progressive +prolific +prominence +prominent +promise +promised +promises +promising +promoter +prompt +promptly +proper +properly +propitious +propitiously +pros +prosper +prosperity +prosperous +prospros +protect +protection +protective +proud +proven +proves +providence +proving +prowess +prudence +prudent +prudently +punctual +pure +purify +purposeful +quaint +qualified +qualify +quicker +quiet +quieter +radiance +radiant +rapid +rapport +rapt +rapture +raptureous +raptureously +rapturous +rapturously +rational +razor-sharp +reachable +readable +readily +ready +reaffirm +reaffirmation +realistic +realizable +reasonable +reasonably +reasoned +reassurance +reassure +receptive +reclaim +recomend +recommend +recommendation +recommendations +recommended +reconcile +reconciliation +record-setting +recover +recovery +rectification +rectify +rectifying +redeem +redeeming +redemption +refine +refined +refinement +reform +reformed +reforming +reforms +refresh +refreshed +refreshing +refund +refunded +regal +regally +regard +rejoice +rejoicing +rejoicingly +rejuvenate +rejuvenated +rejuvenating +relaxed +relent +reliable +reliably +relief +relish +remarkable +remarkably +remedy +remission +remunerate +renaissance +renewed +renown +renowned +replaceable +reputable +reputation +resilient +resolute +resound +resounding +resourceful +resourcefulness +respect +respectable +respectful +respectfully +respite +resplendent +responsibly +responsive +restful +restored +restructure +restructured +restructuring +retractable +revel +revelation +revere +reverence +reverent +reverently +revitalize +revival +revive +revives +revolutionary +revolutionize +revolutionized +revolutionizes +reward +rewarding +rewardingly +rich +richer +richly +richness +right +righten +righteous +righteously +righteousness +rightful +rightfully +rightly +rightness +risk-free +robust +rock-star +rock-stars +rockstar +rockstars +romantic +romantically +romanticize +roomier +roomy +rosy +safe +safely +sagacity +sagely +saint +saintliness +saintly +salutary +salute +sane +satisfactorily +satisfactory +satisfied +satisfies +satisfy +satisfying +satisified +saver +savings +savior +savvy +scenic +seamless +seasoned +secure +securely +selective +self-determination +self-respect +self-satisfaction +self-sufficiency +self-sufficient +sensation +sensational +sensationally +sensations +sensible +sensibly +sensitive +serene +serenity +sexy +sharp +sharper +sharpest +shimmering +shimmeringly +shine +shiny +significant +silent +simpler +simplest +simplified +simplifies +simplify +simplifying +sincere +sincerely +sincerity +skill +skilled +skillful +skillfully +slammin +sleek +slick +smart +smarter +smartest +smartly +smile +smiles +smiling +smilingly +smitten +smooth +smoother +smoothes +smoothest +smoothly +snappy +snazzy +sociable +soft +softer +solace +solicitous +solicitously +solid +solidarity +soothe +soothingly +sophisticated +soulful +soundly +soundness +spacious +sparkle +sparkling +spectacular +spectacularly +speedily +speedy +spellbind +spellbinding +spellbindingly +spellbound +spirited +spiritual +splendid +splendidly +splendor +spontaneous +sporty +spotless +sprightly +stability +stabilize +stable +stainless +standout +state-of-the-art +stately +statuesque +staunch +staunchly +staunchness +steadfast +steadfastly +steadfastness +steadiest +steadiness +steady +stellar +stellarly +stimulate +stimulates +stimulating +stimulative +stirringly +straighten +straightforward +streamlined +striking +strikingly +striving +strong +stronger +strongest +stunned +stunning +stunningly +stupendous +stupendously +sturdier +sturdy +stylish +stylishly +stylized +suave +suavely +sublime +subsidize +subsidized +subsidizes +subsidizing +substantive +succeed +succeeded +succeeding +succeeds +succes +success +successes +successful +successfully +suffice +sufficed +suffices +sufficient +sufficiently +suitable +sumptuous +sumptuously +sumptuousness +super +superb +superbly +superior +superiority +supple +support +supported +supporter +supporting +supportive +supports +supremacy +supreme +supremely +supurb +supurbly +surmount +surpass +surreal +survival +survivor +sustainability +sustainable +swank +swankier +swankiest +swanky +sweeping +sweet +sweeten +sweetheart +sweetly +sweetness +swift +swiftness +talent +talented +talents +tantalize +tantalizing +tantalizingly +tempt +tempting +temptingly +tenacious +tenaciously +tenacity +tender +tenderly +terrific +terrifically +thank +thankful +thinner +thoughtful +thoughtfully +thoughtfulness +thrift +thrifty +thrill +thrilled +thrilling +thrillingly +thrills +thrive +thriving +thumb-up +thumbs-up +tickle +tidy +time-honored +timely +tingle +titillate +titillating +titillatingly +togetherness +tolerable +toll-free +top +top-notch +top-quality +topnotch +tops +tough +tougher +toughest +traction +tranquil +tranquility +transparent +treasure +tremendously +trendy +triumph +triumphal +triumphant +triumphantly +trivially +trophy +trouble-free +trump +trumpet +trust +trusted +trusting +trustingly +trustworthiness +trustworthy +trusty +truthful +truthfully +truthfulness +twinkly +ultra-crisp +unabashed +unabashedly +unaffected +unassailable +unbeatable +unbiased +unbound +uncomplicated +unconditional +undamaged +undaunted +understandable +undisputable +undisputably +undisputed +unencumbered +unequivocal +unequivocally +unfazed +unfettered +unforgettable +unity +unlimited +unmatched +unparalleled +unquestionable +unquestionably +unreal +unrestricted +unrivaled +unselfish +unwavering +upbeat +upgradable +upgradeable +upgraded +upheld +uphold +uplift +uplifting +upliftingly +upliftment +upscale +usable +useable +useful +user-friendly +user-replaceable +valiant +valiantly +valor +valuable +variety +venerate +verifiable +veritable +versatile +versatility +vibrant +vibrantly +victorious +victory +viewable +vigilance +vigilant +virtue +virtuous +virtuously +visionary +vivacious +vivid +vouch +vouchsafe +warm +warmer +warmhearted +warmly +warmth +wealthy +welcome +well +well-backlit +well-balanced +well-behaved +well-being +well-bred +well-connected +well-educated +well-established +well-informed +well-intentioned +well-known +well-made +well-managed +well-mannered +well-positioned +well-received +well-regarded +well-rounded +well-run +well-wishers +wellbeing +whoa +wholeheartedly +wholesome +whooa +whoooa +wieldy +willing +willingly +willingness +win +windfall +winnable +winner +winners +winning +wins +wisdom +wise +wisely +witty +won +wonder +wonderful +wonderfully +wonderous +wonderously +wonders +wondrous +woo +work +workable +worked +works +world-famous +worth +worth-while +worthiness +worthwhile +worthy +wow +wowed +wowing +wows +yay +youthful +zeal +zenith +zest +zippy