Skip to content

Commit

Permalink
AppEngine Standard Application Version resource. (#1884)
Browse files Browse the repository at this point in the history
* Added appengine standard version resource

* Update products/appengine/api.yaml

* Update tracked submodules -> HEAD on Mon Aug 26 17:16:59 UTC 2019

Tracked submodules are build/terraform-beta build/terraform-mapper build/terraform build/ansible build/inspec.
  • Loading branch information
khanali21 authored and modular-magician committed Aug 26, 2019
1 parent ecacdcb commit 32756c9
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 6 deletions.
2 changes: 1 addition & 1 deletion build/ansible
Submodule ansible updated 0 files
2 changes: 1 addition & 1 deletion build/terraform
2 changes: 1 addition & 1 deletion build/terraform-beta
4 changes: 4 additions & 0 deletions products/appengine/ansible.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ overrides: !ruby/object:Overrides::ResourceOverrides
# differently than Terraform.
identity:
- priority
Service: !ruby/object:Overrides::Ansible::ResourceOverride
exclude: true
StandardAppVersion: !ruby/object:Overrides::Ansible::ResourceOverride
exclude: true
files: !ruby/object:Provider::Config::Files
resource:
<%= lines(indent(compile('provider/ansible/resource~compile.yaml'), 4)) -%>
265 changes: 263 additions & 2 deletions products/appengine/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ objects:
properties:
- !ruby/object:Api::Type::String
name: 'description'
description: 'An optional string description of this rule.'
description: |
An optional string description of this rule.
required: false
- !ruby/object:Api::Type::String
name: 'sourceRange'
description: 'IP address or range, defined using CIDR notation, of requests that this rule applies to.'
description: |
IP address or range, defined using CIDR notation, of requests that this rule applies to.
required: true
- !ruby/object:Api::Type::Enum
name: 'action'
Expand All @@ -64,3 +66,262 @@ objects:
- UNSPECIFIED_ACTION
- ALLOW
- DENY
- !ruby/object:Api::Resource
name: 'Service'
description: |
A Service resource is a logical component of an application that can share state and communicate in a secure fashion with other services.
For example, an application that handles customer requests might include separate services to handle tasks such as backend data analysis or API requests from mobile devices.
Each service has a collection of versions that define a specific set of code used to implement the functionality of that service.
base_url: 'apps/{{project}}/services'
self_link: 'apps/{{project}}/services/{{id}}'
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Official Documentation':
'https://cloud.google.com/appengine/docs/admin-api/deploying-overview'
api: 'https://cloud.google.com/appengine/docs/admin-api/reference/rest/v1/apps.services'
properties:
- !ruby/object:Api::Type::String
name: 'name'
output: true
description: |
Full path to the Service resource in the API. Example apps/myapp/services/default.
This field is used in responses only. Any value specified here in a request is ignored.
- !ruby/object:Api::Type::String
name: 'id'
output: true
description: |
Relative name of the service within the application. Example default.
- !ruby/object:Api::Resource
name: 'StandardAppVersion'
description: |
Standard App Version resource to create a new version of standard GAE Application.
Currently supporting Zip and File Containers.
Currently does not support async operation checking.
base_url: 'apps/{{project}}/services/{{service}}/versions'
delete_url: 'apps/{{project}}/services/{{service}}/versions/{{version_id}}'
delete_verb: :DELETE
update_url: 'apps/{{project}}/services/{{service}}/versions'
update_verb: :POST
update_mask: false
self_link: 'apps/{{project}}/services/{{service}}/versions/{{version_id}}'
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Official Documentation':
'https://cloud.google.com/appengine/docs/admin-api/deploying-overview'
api: 'https://cloud.google.com/appengine/docs/admin-api/reference/rest/v1/apps.services.versions'
async: !ruby/object:Api::Async
operation: !ruby/object:Api::Async::Operation
kind: 'appengine#operation'
path: 'name'
base_url: 'projects/{{project}}/global/operations/{{op_id}}'
wait_ms: 1000
result: !ruby/object:Api::Async::Result
path: 'targetLink'
status: !ruby/object:Api::Async::Status
path: 'status'
complete: 'DONE'
allowed:
- 'PENDING'
- 'RUNNING'
- 'DONE'
error: !ruby/object:Api::Async::Error
path: 'error/errors'
message: 'message'
parameters:
- !ruby/object:Api::Type::ResourceRef
name: 'service'
url_param_only: true
resource: 'Service'
imports: 'name'
description: |
AppEngine service resource
properties:
- !ruby/object:Api::Type::String
name: 'name'
output: true
description: |
Full path to the Version resource in the API. Example, "v1".
- !ruby/object:Api::Type::String
name: 'id'
input: true
description: |
Relative name of the version within the service. For example, `v1`. Version names can contain only lowercase letters, numbers, or hyphens. Reserved names,"default", "latest", and any name with the prefix "ah-".
- !ruby/object:Api::Type::String
name: 'runtime'
description: |
Desired runtime. Example python27.
required: true
- !ruby/object:Api::Type::Boolean
name: 'threadsafe'
description: |
Whether multiple requests can be dispatched to this version at once.
- !ruby/object:Api::Type::String
name: 'runtimeApiVersion'
description: |
The version of the API in the given runtime environment.
Please see the app.yaml reference for valid values at https://cloud.google.com/appengine/docs/standard//config/appref
- !ruby/object:Api::Type::Array
name: 'handlers'
description: |
An ordered list of URL-matching patterns that should be applied to incoming requests.
The first matching URL handles the request and other request handlers are not attempted.
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::String
name: 'urlRegex'
description: |
URL prefix. Uses regular expression syntax, which means regexp special characters must be escaped, but should not contain groupings.
All URLs that begin with this prefix are handled by this handler, using the portion of the URL after the prefix as part of the file path.
- !ruby/object:Api::Type::Enum
name: 'securityLevel'
required: false
description: |
Security (HTTPS) enforcement for this URL.
values:
- :SECURE_UNSPECIFIED
- :SECURE_DEFAULT
- :SECURE_NEVER
- :SECURE_OPTIONAL
- :SECURE_ALWAYS
- !ruby/object:Api::Type::Enum
name: 'login'
description: |
Methods to restrict access to a URL based on login status.
required: false
values:
- :LOGIN_UNSPECIFIED
- :LOGIN_OPTIONAL
- :LOGIN_ADMIN
- :LOGIN_REQUIRED
- !ruby/object:Api::Type::Enum
name: 'authFailAction'
description: |
Actions to take when the user is not logged in.
required: false
values:
- :AUTH_FAIL_ACTION_UNSPECIFIED
- :AUTH_FAIL_ACTION_REDIRECT
- :AUTH_FAIL_ACTION_UNAUTHORIZED
- !ruby/object:Api::Type::Enum
name: 'redirectHttpResponseCode'
description: |
Redirect codes.
required: false
values:
- :REDIRECT_HTTP_RESPONSE_CODE_UNSPECIFIED
- :REDIRECT_HTTP_RESPONSE_CODE_301
- :REDIRECT_HTTP_RESPONSE_CODE_302
- :REDIRECT_HTTP_RESPONSE_CODE_303
- :REDIRECT_HTTP_RESPONSE_CODE_307
- !ruby/object:Api::Type::NestedObject
name: 'script'
description: |
Executes a script to handle the requests that match this URL pattern.
Only the auto value is supported for Node.js in the App Engine standard environment, for example "script:" "auto".
properties:
- !ruby/object:Api::Type::String
name: 'scriptPath'
description: |
Path to the script from the application root directory.
- !ruby/object:Api::Type::NestedObject
name: 'staticFiles'
description: |
Files served directly to the user for a given URL, such as images, CSS stylesheets, or JavaScript source files. Static file handlers describe which files in the application directory are static files, and which URLs serve them.
properties:
- !ruby/object:Api::Type::String
name: 'path'
description: |
Path to the static files matched by the URL pattern, from the application root directory. The path can refer to text matched in groupings in the URL pattern.
- !ruby/object:Api::Type::String
name: 'uploadPathRegex'
description: |
Regular expression that matches the file paths for all files that should be referenced by this handler.
- !ruby/object:Api::Type::KeyValuePairs
name: 'httpHeaders'
description: |
HTTP headers to use for all responses from these URLs.
An object containing a list of "key:value" value pairs.".
- !ruby/object:Api::Type::String
name: 'mimeType'
description: |
MIME type used to serve all files served by this handler.
Defaults to file-specific MIME types, which are derived from each file's filename extension.
- !ruby/object:Api::Type::String
name: 'expiration'
description: |
Time a static file served by this handler should be cached by web proxies and browsers.
A duration in seconds with up to nine fractional digits, terminated by 's'. Example "3.5s".
- !ruby/object:Api::Type::Boolean
name: 'requireMatchingFile'
description: |
Whether this handler should match the request if the file referenced by the handler does not exist.
- !ruby/object:Api::Type::Boolean
name: 'applicationReadable'
description: |
Whether files should also be uploaded as code data. By default, files declared in static file handlers are uploaded as static data and are only served to end users; they cannot be read by the application. If enabled, uploads are charged against both your code and static data storage resource quotas.
- !ruby/object:Api::Type::Array
name: 'libraries'
description: |
Configuration for third-party Python runtime libraries that are required by the application.
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::String
name: 'name'
description: |
Name of the library. Example "django".
- !ruby/object:Api::Type::String
name: 'version'
description: |
Version of the library to select, or "latest".
- !ruby/object:Api::Type::KeyValuePairs
name: 'envVariables'
description: |
Environment variables available to the application.
- !ruby/object:Api::Type::NestedObject
name: 'deployment'
description: |
Code and application artifacts that make up this version.
required: false
properties:
- !ruby/object:Api::Type::NestedObject
name: 'zip'
description: 'Zip File'
required: false
properties:
- !ruby/object:Api::Type::String
name: 'sourceUrl'
description: 'Source URL'
- !ruby/object:Api::Type::Integer
name: 'filesCount'
description: 'files count'
required: false
- !ruby/object:Api::Type::Map
name: 'files'
description: |
Manifest of the files stored in Google Cloud Storage that are included as part of this version.
All files must be readable using the credentials supplied with this call.
required: false
key_name: 'name'
key_description: |
name of file
value_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::String
name: 'sha1Sum'
description: |
SHA1 checksum of the file
- !ruby/object:Api::Type::String
name: 'sourceUrl'
description: |
Source URL
- !ruby/object:Api::Type::NestedObject
name: 'entrypoint'
description: |
The entrypoint for the application.
required: false
properties:
- !ruby/object:Api::Type::String
name: 'shell'
description: |
The format should be a shell command that can be fed to bash -c.
42 changes: 41 additions & 1 deletion products/appengine/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,47 @@ overrides: !ruby/object:Overrides::ResourceOverrides
project_id: "test-project"
test_env_vars:
org_id: :ORG_ID

StandardAppVersion: !ruby/object:Overrides::Terraform::ResourceOverride
id_format: "apps/{{project}}/services/{{service}}/versions/{{version_id}}"
import_format: ["apps/{{project}}/services/{{service}}/versions/{{version_id}}"]
mutex: "apps/{{project}}/services/{{service}}"
parameters:
service: !ruby/object:Overrides::Terraform::PropertyOverride
default_from_api: true
required: false
virtual_fields:
- !ruby/object:Provider::Terraform::VirtualFields
name: 'noop_on_destroy'
description: |
If set to `true`, the application version will not be deleted.
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_delete: templates/terraform/custom_delete/noop_on_destroy_appengine_version.go.erb
test_check_destroy: templates/terraform/custom_check_destroy/appengine_version.go.erb
properties:
id: !ruby/object:Overrides::Terraform::PropertyOverride
name: 'version_id'
deployment: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
entrypoint: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
envVariables: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
threadsafe: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
examples:
- !ruby/object:Provider::Terraform::Examples
name: "app_engine_standard_app_version"
primary_resource_id: "version_id"
ignore_read_extra:
- "noop_on_destroy"
vars:
project_id: "test-project"
bucket_name: "appengine-static-content"
service_name: "tf-test-service"
test_env_vars:
org_id: :ORG_ID
Service: !ruby/object:Overrides::Terraform::ResourceOverride
exclude: true
# This is for copying files over
files: !ruby/object:Provider::Config::Files
# These files have templating (ERB) code that will be run.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
log.Printf("[DEBUG] Ignoring destroy during test")
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
if d.Get("noop_on_destroy") == true {
log.Printf("[DEBUG] Keeping the StandardAppVersion %q", d.Id())
return nil
}
config := meta.(*Config)

project, err := getProject(d, config)
if err != nil {
return err
}

lockName, err := replaceVars(d, config, "apps/{{project}}/services/{{service}}")
if err != nil {
return err
}
mutexKV.Lock(lockName)
defer mutexKV.Unlock(lockName)

url, err := replaceVars(d, config, "{{AppEngineBasePath}}apps/{{project}}/services/{{service}}/versions/{{version_id}}")
if err != nil {
return err
}

var obj map[string]interface{}
log.Printf("[DEBUG] Deleting StandardAppVersion %q", d.Id())

res, err := sendRequestWithTimeout(config, "DELETE", project, url, obj, d.Timeout(schema.TimeoutDelete))
if err != nil {
return handleNotFoundError(err, d, "StandardAppVersion")
}

op := &appengine.Operation{}
err = Convert(res, op)
if err != nil {
return err
}

err = appEngineOperationWaitTime(
config.clientAppEngine, op, project, "Deleting StandardAppVersion",
int(d.Timeout(schema.TimeoutDelete).Minutes()))

if err != nil {
return err
}

log.Printf("[DEBUG] Finished deleting StandardAppVersion %q: %#v", d.Id(), res)
return nil


Loading

0 comments on commit 32756c9

Please sign in to comment.