in lib/tools_api/src/main/java/com/google/appengine/tools/admin/AppYamlTranslator.java [142:404]
private void translateAppEngineWebXml(StringBuilder builder) {
if (appEngineWebXml.getAppId() != null) {
builder.append("application: '" + appEngineWebXml.getAppId() + "'\n");
}
builder.append("runtime: " + runtime + "\n");
if (appEngineWebXml.getUseVm()) {
builder.append("vm: True\n");
}
if (appEngineWebXml.isFlexible()) {
builder.append("env: " + appEngineWebXml.getEnv() + "\n");
}
if (appEngineWebXml.getEntrypoint() != null) {
builder.append("entrypoint: '" + appEngineWebXml.getEntrypoint() + "'\n");
}
if (appEngineWebXml.getRuntimeChannel() != null) {
builder.append("runtime_channel: " + appEngineWebXml.getRuntimeChannel() + "\n");
}
if (appEngineWebXml.getMajorVersionId() != null) {
builder.append("version: '" + appEngineWebXml.getMajorVersionId() + "'\n");
}
if (appEngineWebXml.getService() != null) {
builder.append("service: '" + appEngineWebXml.getService() + "'\n");
} else if (appEngineWebXml.getModule() != null) {
builder.append("module: '" + appEngineWebXml.getModule() + "'\n");
}
if (appEngineWebXml.getInstanceClass() != null) {
builder.append("instance_class: " + appEngineWebXml.getInstanceClass() + "\n");
}
if (!appEngineWebXml.getAutomaticScaling().isEmpty()) {
builder.append("automatic_scaling:\n");
AppEngineWebXml.AutomaticScaling settings = appEngineWebXml.getAutomaticScaling();
appendIfNotNull(builder, " min_pending_latency: ", settings.getMinPendingLatency());
appendIfNotNull(builder, " max_pending_latency: ", settings.getMaxPendingLatency());
appendIfNotNull(builder, " min_idle_instances: ", settings.getMinIdleInstances());
appendIfNotNull(builder, " max_idle_instances: ", settings.getMaxIdleInstances());
appendIfNotNull(builder, " max_concurrent_requests: ", settings.getMaxConcurrentRequests());
appendIfNotNull(builder, " min_num_instances: ", settings.getMinNumInstances());
appendIfNotNull(builder, " max_num_instances: ", settings.getMaxNumInstances());
appendIfNotNull(builder, " cool_down_period_sec: ", settings.getCoolDownPeriodSec());
// GAE Standard new clone scheduler:
// I know, having min_num_instances and min_instances is confusing. b/70626925.
appendIfNotNull(builder, " min_instances: ", settings.getMinInstances());
appendIfNotNull(builder, " max_instances: ", settings.getMaxInstances());
appendIfNotNull(builder, " target_cpu_utilization: ", settings.getTargetCpuUtilization());
appendIfNotNull(
builder, " target_throughput_utilization: ", settings.getTargetThroughputUtilization());
CpuUtilization cpuUtil = settings.getCpuUtilization();
if (cpuUtil != null
&& (cpuUtil.getTargetUtilization() != null
|| cpuUtil.getAggregationWindowLengthSec() != null)) {
builder.append(" cpu_utilization:\n");
appendIfNotNull(builder, " target_utilization: ", cpuUtil.getTargetUtilization());
appendIfNotNull(
builder, " aggregation_window_length_sec: ",
cpuUtil.getAggregationWindowLengthSec());
}
appendIfNotNull(
builder, " target_network_sent_bytes_per_sec: ",
settings.getTargetNetworkSentBytesPerSec());
appendIfNotNull(
builder, " target_network_sent_packets_per_sec: ",
settings.getTargetNetworkSentPacketsPerSec());
appendIfNotNull(
builder, " target_network_received_bytes_per_sec: ",
settings.getTargetNetworkReceivedBytesPerSec());
appendIfNotNull(
builder, " target_network_received_packets_per_sec: ",
settings.getTargetNetworkReceivedPacketsPerSec());
appendIfNotNull(
builder, " target_disk_write_bytes_per_sec: ",
settings.getTargetDiskWriteBytesPerSec());
appendIfNotNull(
builder, " target_disk_write_ops_per_sec: ",
settings.getTargetDiskWriteOpsPerSec());
appendIfNotNull(
builder, " target_disk_read_bytes_per_sec: ",
settings.getTargetDiskReadBytesPerSec());
appendIfNotNull(
builder, " target_disk_read_ops_per_sec: ",
settings.getTargetDiskReadOpsPerSec());
appendIfNotNull(
builder, " target_request_count_per_sec: ",
settings.getTargetRequestCountPerSec());
appendIfNotNull(
builder, " target_concurrent_requests: ",
settings.getTargetConcurrentRequests());
if (!settings.getCustomMetrics().isEmpty()) {
if (!appEngineWebXml.isFlexible()) {
throw new AppEngineConfigException("custom-metrics is only available in the AppEngine "
+ "Flexible environment.");
}
builder.append(" custom_metrics:\n");
for (CustomMetricUtilization metric : settings.getCustomMetrics()) {
builder.append(" - metric_name: '" + metric.getMetricName() + "'\n");
builder.append(" target_type: '" + metric.getTargetType() + "'\n");
appendIfNotNull(builder, " target_utilization: ", metric.getTargetUtilization());
appendIfNotNull(builder,
" single_instance_assignment: ",
metric.getSingleInstanceAssignment());
if (metric.getFilter() != null) {
builder.append(" filter: '" + metric.getFilter() + "'\n");
}
}
}
}
if (!appEngineWebXml.getManualScaling().isEmpty()) {
builder.append("manual_scaling:\n");
AppEngineWebXml.ManualScaling settings = appEngineWebXml.getManualScaling();
builder.append(" instances: " + settings.getInstances() + "\n");
}
if (!appEngineWebXml.getBasicScaling().isEmpty()) {
builder.append("basic_scaling:\n");
AppEngineWebXml.BasicScaling settings = appEngineWebXml.getBasicScaling();
builder.append(" max_instances: " + settings.getMaxInstances() + "\n");
appendIfNotNull(builder, " idle_timeout: ", settings.getIdleTimeout());
}
Collection<String> services = appEngineWebXml.getInboundServices();
if (!services.isEmpty()) {
builder.append("inbound_services:\n");
for (String service : services) {
builder.append("- " + service + "\n");
}
}
// Precompilation is only for the Standard environment.
if (appEngineWebXml.getPrecompilationEnabled()
&& !appEngineWebXml.getUseVm()
&& !appEngineWebXml.isFlexible()
&& !appEngineWebXml.isJava11OrAbove()) {
builder.append("derived_file_type:\n");
builder.append("- java_precompiled\n");
}
if (appEngineWebXml.getThreadsafe() && !appEngineWebXml.isJava11OrAbove()) {
builder.append("threadsafe: True\n");
}
if (appEngineWebXml.getAppEngineApis() && appEngineWebXml.isJava11OrAbove()) {
builder.append("app_engine_apis: True\n");
}
if (appEngineWebXml.getThreadsafeValueProvided() && appEngineWebXml.isJava11OrAbove()) {
System.out.println(
"Warning: The "
+ appEngineWebXml.getRuntime()
+ " runtime does not use the <threadsafe> element"
+ " in appengine-web.xml anymore");
System.out.println(
"Instead, you can use the <max-concurrent-requests> element in <automatic-scaling>.");
}
if (appEngineWebXml.getAutoIdPolicy() != null) {
builder.append("auto_id_policy: " + appEngineWebXml.getAutoIdPolicy() + "\n");
} else {
// NOTE: The YAML parsing and validation done in the admin console must
// set the value for unspecified auto_id_policy to 'legacy' in order to achieve
// the desired behavior for previous SDK versions. But the desired value for
// unspecified auto_id_policy in current and future SDK versions is 'default'.
// Therefore in new SDK versions we intercept unspecified auto_id_policy here.
builder.append("auto_id_policy: default\n");
}
if (appEngineWebXml.getCodeLock()) {
builder.append("code_lock: True\n");
}
if (appEngineWebXml.getVpcAccessConnector() != null) {
VpcAccessConnector connector = appEngineWebXml.getVpcAccessConnector();
builder.append("vpc_access_connector:\n");
builder.append(" name: " + connector.getName() + "\n");
if (connector.getEgressSetting().isPresent()) {
builder.append(" egress_setting: " + connector.getEgressSetting().get() + "\n");
}
}
if (appEngineWebXml.getServiceAccount() != null) {
builder.append("service_account: " + appEngineWebXml.getServiceAccount() + "\n");
}
List<AdminConsolePage> adminConsolePages = appEngineWebXml.getAdminConsolePages();
if (!adminConsolePages.isEmpty()) {
builder.append("admin_console:\n");
builder.append(" pages:\n");
for (AdminConsolePage page : adminConsolePages) {
builder.append(" - name: " + page.getName() + "\n");
builder.append(" url: " + page.getUrl() + "\n");
}
}
List<ErrorHandler> errorHandlers = appEngineWebXml.getErrorHandlers();
if (!errorHandlers.isEmpty()) {
builder.append("error_handlers:\n");
for (ErrorHandler handler : errorHandlers) {
String fileName = handler.getFile();
if (!fileName.startsWith("/")) {
fileName = "/" + fileName;
}
// TODO: Consider whether we should be adding the
// public root to this path.
if (!staticFiles.contains("__static__" + fileName)) {
throw new AppEngineConfigException("No static file found for error handler: "
+ fileName + ", out of " + staticFiles);
}
// error_handlers doesn't want a leading slash here.
builder.append("- file: __static__" + fileName + "\n");
if (handler.getErrorCode() != null) {
builder.append(" error_code: " + handler.getErrorCode() + "\n");
}
String mimeType = webXml.getMimeTypeForPath(handler.getFile());
if (mimeType != null) {
builder.append(" mime_type: " + mimeType + "\n");
}
}
}
if (backendsXml != null) {
builder.append(backendsXml.toYaml());
}
// Only one api config, it is a singleton, and multiple APIs are served
// from subpaths within the namespace.
// TODO: Verify script: is required.
ApiConfig apiConfig = appEngineWebXml.getApiConfig();
if (apiConfig != null) {
builder.append("api_config:\n");
builder.append(" url: " + apiConfig.getUrl() + "\n");
builder.append(" script: unused\n");
}
// For beta-settings, we allow anything and defer to the later app.yaml processing
// to detect invalid values.
appendBetaSettings(appEngineWebXml.getBetaSettings(), builder);
appendEnvVariables(appEngineWebXml.getEnvironmentVariables(), builder);
appendBuildEnvVariables(appEngineWebXml.getBuildEnvironmentVariables(), builder);
if (appEngineWebXml.getUseVm() || appEngineWebXml.isFlexible()) {
if (appEngineWebXml.getHealthCheck() != null) {
appendHealthCheck(appEngineWebXml.getHealthCheck(), builder);
}
if (appEngineWebXml.getLivenessCheck() != null) {
appendLivenessCheck(appEngineWebXml.getLivenessCheck(), builder);
}
if (appEngineWebXml.getReadinessCheck() != null) {
appendReadinessCheck(appEngineWebXml.getReadinessCheck(), builder);
}
appendResources(appEngineWebXml.getResources(), builder);
appendNetwork(appEngineWebXml.getNetwork(), builder);
}
}