Skip to content

Commit

Permalink
Add Templating (#792)
Browse files Browse the repository at this point in the history
* Add Templating

1. App Engine Sockets (moved from GoogleArchive)
2. J8 GAE Info now uses ThymeLeaf templating
3. Flex GAE Info for combat (WL’d only) sample
4. J8 Metadata - Only uses the Metadata server

* add to parent

1. add a few things to the parent pom.xml (both app engine &
appengine-java8)
2. Fix some copyrights.
  • Loading branch information
lesv authored Aug 8, 2017
1 parent 0a46f17 commit 17f6cd5
Show file tree
Hide file tree
Showing 27 changed files with 1,548 additions and 99 deletions.
6 changes: 6 additions & 0 deletions appengine-java8/gaeinfo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Copyright 2017 Google Inc.
<version>2.8.1</version>
</dependency>

<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,23 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;


// [START example]
Expand All @@ -46,7 +47,7 @@
urlPatterns = "/gaeinfo")
public class GaeInfoServlet extends HttpServlet {

final String[] v1 = {
private final String[] metaPath = {
"/computeMetadata/v1/project/numeric-project-id", // (pending)
"/computeMetadata/v1/project/project-id",
"/computeMetadata/v1/instance/zone",
Expand All @@ -57,44 +58,30 @@ public class GaeInfoServlet extends HttpServlet {
// "/computeMetadata/v1/instance/service-accounts/default/token"
};

final String[] v1Acct = {
final String[] metaServiceAcct = {
"/computeMetadata/v1/instance/service-accounts/{account}/aliases",
"/computeMetadata/v1/instance/service-accounts/{account}/email",
"/computeMetadata/v1/instance/service-accounts/{account}/scopes",
// Tokens work - but are a security risk to display
// "/computeMetadata/v1/instance/service-accounts/{account}/token"
};

final String metadata = "http://metadata.google.internal";
private final String metadata = "http://metadata.google.internal";
private TemplateEngine templateEngine;

public final OkHttpClient ok = new OkHttpClient.Builder()
// Use OkHttp from Square as it's quite easy to use for simple fetches.
private final OkHttpClient ok = new OkHttpClient.Builder()
.readTimeout(500, TimeUnit.MILLISECONDS) // Don't dawdle
.writeTimeout(500, TimeUnit.MILLISECONDS)
.build();

public Gson gson = new GsonBuilder()
// Setup to pretty print returned json
private final Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
public JsonParser jp = new JsonParser();

StringBuilder table(String title, String c) {
StringBuilder sb = new StringBuilder();
sb.append("<h3>");
sb.append(title);
sb.append("</h3><table>");
sb.append(c);
sb.append("</table>");
return sb;
}

String tr(String c) {
return "<tr>" + c + "</tr>";
}

String td(String s) {
return "<td>" + s + "</td>";
}
private final JsonParser jp = new JsonParser();

// Fetch Metadata
String fetchMetadata(String key) throws IOException {
Request request = new Request.Builder()
.url(metadata + key)
Expand All @@ -106,122 +93,126 @@ String fetchMetadata(String key) throws IOException {
return response.body().string();
}

String recursMetadata(String prefix) throws IOException {
String fetchJsonMetadata(String prefix) throws IOException {
Request request = new Request.Builder()
.url(metadata + prefix + "?recursive=true")
.url(metadata + prefix )
.addHeader("Metadata-Flavor", "Google")
.get()
.build();

Response response = ok.newCall(request).execute();

// Convert json to prety json
return gson.toJson(jp.parse(response.body().string()));
}


@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html");
PrintWriter p = resp.getWriter();
StringBuilder sb = new StringBuilder(4096);
public void init() {
// Setup ThymeLeaf
ServletContextTemplateResolver templateResolver =
new ServletContextTemplateResolver(this.getServletContext());

templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCacheTTLMs(Long.valueOf(1200000L)); // TTL=20m

p.print("<html><body>");
// Cache is set to true by default. Set to false if you want templates to
// be automatically updated when modified.
templateResolver.setCacheable(true);

templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
}


@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String key ="";
final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
WebContext ctx = new WebContext(req, resp, getServletContext(), req.getLocale());

sb.append(table("AppIdentity",
tr(td("ServiceAccountName") + td(appIdentity.getServiceAccountName()))
+ tr(td("GCS Bucket") + td(appIdentity.getDefaultGcsBucketName()))
));
resp.setContentType("text/html");

ctx.setVariable("production", SystemProperty.environment.value().name());
ctx.setVariable("ServiceAccountName", appIdentity.getServiceAccountName());
ctx.setVariable("gcs", appIdentity.getDefaultGcsBucketName());

sb.append(table("SystemProperties",
tr(td("appId") + td(SystemProperty.applicationId.get()))
+ tr(td("appVer") + td(SystemProperty.applicationVersion.get()))
+ tr(td("version") + td(SystemProperty.version.get()))
+ tr(td("environment") + td(SystemProperty.environment.get()))
));
ctx.setVariable("appId", SystemProperty.applicationId.get());
ctx.setVariable("appVer", SystemProperty.applicationVersion.get());
ctx.setVariable("version", SystemProperty.version.get());
ctx.setVariable("environment", SystemProperty.environment.get());

// Environment Atributes
ApiProxy.Environment env = ApiProxy.getCurrentEnvironment();
Map<String, Object> attr = env.getAttributes();
TreeMap<String, String> m = new TreeMap<>();

StringBuilder c = new StringBuilder(1024);
for (String key : attr.keySet()) {
Object o = attr.get(key);
for (String k : attr.keySet()) {
Object o = attr.get(k);

if (o.getClass().getCanonicalName().equals("java.lang.String")) {
c.append(tr(td(key) + td((String) o)));
m.put(k, (String) o);
} else if (o.getClass().getCanonicalName().equals("java.lang.Boolean")) {
m.put(k, ((Boolean) o).toString());
} else {
c.append(tr(td(key) + td(o.getClass().getCanonicalName())));
m.put(k, "a " + o.getClass().getCanonicalName());
}
}
sb.append(table("Environment Attributes", c.toString()));
ctx.setVariable("attribs", m);

c = new StringBuilder(1024);
m = new TreeMap<>();
for (Enumeration<String> e = req.getHeaderNames(); e.hasMoreElements(); ) {
String key = e.nextElement();
String val = req.getHeader(key);
c.append(tr(td(key) + td(val)));
key = e.nextElement();
m.put(key, req.getHeader(key));
}
sb.append(table("Headers", c.toString()));
ctx.setVariable("headers", m);

Cookie[] cookies = req.getCookies();
m = new TreeMap<>();
if (cookies != null && cookies.length != 0) {
c = new StringBuilder();
for (Cookie co : cookies) {
c.append(tr(td(co.getName()) + td(co.getValue()) + td(co.getComment())
+ td(co.getPath()) + td(Integer.toString(co.getMaxAge()))));
m.put(co.getName(), co.getValue());
}
sb.append(table("Cookies", c.toString()));
}
ctx.setVariable("cookies", m);

Properties properties = System.getProperties();
c = new StringBuilder(1024);
m = new TreeMap<>();
for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
c.append(tr(td(key) + td((String) properties.get(key))));
key = (String) e.nextElement();
m.put(key, (String) properties.get(key));
}
sb.append(table("Java SystemProperties", c.toString()));
ctx.setVariable("systemprops", m);

Map<String, String> envVar = System.getenv();
c = new StringBuilder(1024);
for (String key : envVar.keySet()) {
c.append(tr(td(key) + td(envVar.get(key))));
}
sb.append(table("Envirionment Variables", c.toString()));
m = new TreeMap<>(envVar);
ctx.setVariable("envvar", m);

// The metadata server is only on a production system
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production) {
c = new StringBuilder(1024);
for (String key : v1) {
String val = fetchMetadata(key);
if (val != null) {
c.append(tr(td(key) + td(val)));
}

m = new TreeMap<>();
for (String k : metaPath) {
m.put(k, fetchMetadata(key));
}
sb.append(table("Metadata", c.toString()));

c = new StringBuilder(1024);
for (String key : v1Acct) {
key = key.replace("{account}", appIdentity.getServiceAccountName());
String val = fetchMetadata(key);
if (val != null) {
c.append(tr(td(key) + td(val)));
}
ctx.setVariable("Metadata", m.descendingMap());

m = new TreeMap<>();
for (String k : metaServiceAcct) {
// substitute a service account for {account}
k = k.replace("{account}", appIdentity.getServiceAccountName());
m.put(k, fetchMetadata(k));
}
sb.append(table("ServiceAccount Metadata", c.toString()));

sb.append("<h3>Recursive service-accounts</h3><pre><code>"
+ recursMetadata("/computeMetadata/v1/instance/service-accounts/")
+ "</code></pre>");
sb.append("<h3>Recursive all metadata</h3><pre><code>"
+ recursMetadata("/")
+ "</code></pre>");
}
ctx.setVariable("sam", m.descendingMap());

sb.append("</body></html>");
p.append(sb);
p.close();
// Recursivly get all info about service accounts -- Note tokens are leftout by default.
ctx.setVariable("rsa",
fetchJsonMetadata("/computeMetadata/v1/instance/service-accounts/?recursive=true"));
// Recursivly get all data on Metadata server.
ctx.setVariable("ram", fetchJsonMetadata("/?recursive=true"));
}

templateEngine.process("index", ctx, resp.getWriter());
}
}
// [END example]
Loading

0 comments on commit 17f6cd5

Please sign in to comment.