Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add KubernetesMetadata extensions #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/v1/accessory.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
schema Accessory(Object):
""" Accessory refers to various runtime capabilities and operational requirements provided by the underlying
infrastructure, such as database, gateway, cache e.g. All specific accessory schema definitions must inherit
the Accessory schema.
"""
28 changes: 11 additions & 17 deletions v1/app_configuration.k → core/v1/app_configuration.k
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
import v1.workload as wl
import extensions.v1 as extv1

schema AppConfiguration:
schema AppConfiguration(Object):
""" AppConfiguration is a developer-centric definition that describes how to run an Application.
This application model builds upon a decade of experience at AntGroup running super large scale
internal developer platform, combined with best-of-breed ideas and practices from the community.

Attributes
----------
workload: wl.Service | wl.Job, default is Undefined, required.
workload: Service | Job, default is Undefined, required.
Workload defines how to run your application code. Currently supported workload profile
includes Service and Job.
accessories: {str:any}, default is Undefined, optional.
Accessories defines a collection of accessories that will be attached to the workload.
labels: {str:str}, default is Undefined, optional.
extensions: [extv1.KubernetesMetadata], default is Undefined, optional.
Labels can be used to attach arbitrary metadata as key-value pairs to resources.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename this description to extensions

annotations: {str:str}, default is Undefined, optional.
Annotations are key/value pairs that attach arbitrary non-identifying metadata to resources.

Examples
--------
# Instantiate an App with a long-running service and its image is "nginx:v1"

import kam as ac
import kam.workload as wl
import kam.workload.container as c
import kam.core.v1 as v1

helloworld : ac.AppConfiguration {
workload: wl.Service {
helloworld : v1.AppConfiguration {
workload: v1.Service {
containers: {
"nginx": c.Container {
"nginx": v1.Container {
image: "nginx:v1"
}
}
Expand All @@ -37,12 +33,10 @@ schema AppConfiguration:
"""

# Workload defines how to run your application code.
workload: wl.Service | wl.Job
workload: Workload

# Accessories defines a collection of accessories that will be attached to the workload.
accessories?: {str:any}
accessories?: {str:Accessory}

###### Other metadata info
# Labels and annotations can be used to attach arbitrary metadata as key-value pairs to resources.
labels?: {str:str}
annotations?: {str:str}
extensions?: [extv1.KubernetesMetadata]
318 changes: 318 additions & 0 deletions core/v1/container.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
import regex

schema Container:
""" Container describes how the Application's tasks are expected to be run. Depending on
the replicas parameter 1 or more containers can be created from each template.

Attributes
----------
image: str, default is Undefined, required.
Image refers to the Docker image name to run for this container.
More info: https://kubernetes.io/docs/concepts/containers/images
command: [str], default is Undefined, optional.
Entrypoint array. Not executed within a shell.
Command will overwrite the ENTRYPOINT value set in the Dockfile, otherwise the Docker
image's ENTRYPOINT is used if this is not provided.
args: [str], default is Undefined, optional.
Arguments to the entrypoint.
Args will overwrite the CMD value set in the Dockfile, otherwise the Docker
image's CMD is used if this is not provided.
env: {str:str}, default is Undefined, optional.
List of environment variables to set in the container.
The value of the environment variable may be static text or a value from a secret.
workingDir: str, default is Undefined, optional.
The working directory of the running process defined in entrypoint.
Default container runtime will be used if this is not specified.
resources: {str:str}, default is Undefined, optional.
Map of resource requirements the container should run with.
The resources parameter is a dict with the key being the resource name and the value being
the resource value.
files: {str:FileSpec}, default is Undefined, optional.
List of files to create in the container.
The files parameter is a dict with the key being the file name in the container and the value
being the target file specification.
dirs: {str:str}, default is Undefined, optional.
Collection of volumes mount into the container's filesystem.
The dirs parameter is a dict with the key being the folder name in the container and the value
being the referenced volume.
livenessProbe: Probe, default is Undefined, optional.
LivenessProbe indicates if a running process is healthy.
Container will be restarted if the probe fails.
readinessProbe: Probe, default is Undefined, optional.
ReadinessProbe indicates whether an application is available to handle requests.
startupProbe: Probe, default is Undefined, optional.
StartupProbe indicates that the container has started for the first time.
Container will be restarted if the probe fails.
lifecycle: Lifecycle, default is Undefined, optional.
Lifecycle refers to actions that the management system should take in response to container lifecycle events.

Examples
--------
import kam.core.v1 as v1

web = v1.Container {
image: "nginx:latest"
command: ["/bin/sh", "-c", "echo hi"]
env: {
"name": "value"
}
resources: {
"cpu": "2"
"memory": "4Gi"
}
}
"""

# Image to run for this container.
image: str

# Entrypoint array.
# The image's ENTRYPOINT is used if this is not provided.
command?: [str]
# Arguments to the entrypoint.
# The image's CMD is used if this is not provided.
args?: [str]
# Collection of environment variables to set in the container.
# The value of environment variable may be static text or a value from a secret.
env?: {str:str}
# The current working directory of the running process defined in entrypoint.
workingDir?: str

# Resource requirements for this container.
resources?: {str:str}

# Files configures one or more files to be created in the container.
files?: {str:FileSpec}
# Dirs configures one or more volumes to be mounted to the specified folder.
dirs?: {str:str}

# Liveness probe for this container.
# Liveness probe indicates if a running process is healthy.
livenessProbe?: Probe
# Readiness probe for this container.
# Readiness probe indicates whether an application is available to handle requests.
readinessProbe?: Probe
# Startup probe for this container.
# Startup probe indicates that the container has started for the first time.
startupProbe?: Probe

# Lifecycle configures actions which should be taken response to container lifecycle
# events.
lifecycle?: Lifecycle

check:
all e in env {
regex.match(e, r"^[-._a-zA-Z][-._a-zA-Z0-9]*$")
} if env, "a valid environment variable name must consist of alphabetic characters, digits, '_', '-', or '.', and must not start with a digit"

schema FileSpec:
""" FileSpec defines the target file in a Container.

Attributes
----------
content: str, default is Undefined, optional.
File content in plain text.
contentFrom: str, default is Undefined, optional.
Source for the file content, reference to a secret of configmap value.
mode: str, default is Undefined, optional.
Mode bits used to set permissions on this file, must be an octal value
between 0000 and 0777 or a decimal value between 0 and 511

Examples
--------
import kam.core.v1 as v1

tmpFile = v1.FileSpec {
content: "some file contents"
mode: "0777"
}
"""

# The content of target file in plain text.
content?: str

# Source for the file content, might be a reference to a secret value.
contentFrom?: str

# Mode bits used to set permissions on this file.
# Defaults to 0644.
mode: str = "0644"

check:
not content or not contentFrom, "content and contentFrom are mutually exclusive"
regex.match(mode, r"^[0-7]{3,4}$"), "valid mode must between 0000 and 0777, both inclusive"

schema Probe:
""" Probe describes a health check to be performed against a container to determine whether it is
alive or ready to receive traffic. There are three probe types: readiness, liveness, and startup.

Attributes
----------
probeHandler: Exec | Http | Tcp, default is Undefined, required.
The action taken to determine the alive or health of a container
initialDelaySeconds: int, default is Undefined, optional.
The number of seconds before health checking is activated.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
timeoutSeconds: int, default is Undefined, optional.
The number of seconds after which the probe times out.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
periodSeconds: int, default is Undefined, optional.
How often (in seconds) to perform the probe.
successThreshold: int, default is Undefined, optional.
Minimum consecutive successes for the probe to be considered successful after having failed.
failureThreshold: int, default is Undefined, optional.
Minimum consecutive failures for the probe to be considered failed after having succeeded.
terminationGracePeriod: int, default is Undefined, optional.
Duration in seconds before terminate gracefully upon probe failure.

Examples
--------
import kam.core.v1 as v1

probe = v1.Probe {
probeHandler: v1.Http {
path: "/healthz"
}
initialDelaySeconds: 10
}
"""

# The action taken to determine the health of a container
probeHandler: Exec | Http | Tcp

# Number of seconds after the container has started before liveness probes are initiated.
initialDelaySeconds?: int

# Number of seconds after which the probe times out.
timeoutSeconds?: int

# How often (in seconds) to perform the probe.
periodSeconds?: int

# Minimum consecutive successes for the probe to be considered successful after having failed.
successThreshold?: int

# Minimum consecutive failures for the probe to be considered failed after having succeeded.
failureThreshold?: int

# Duration in seconds before terminate gracefully upon probe failure.
terminationGracePeriod?: int

check:
initialDelaySeconds >= 0 if initialDelaySeconds, "initialDelaySeconds must be greater than or equal to 0"
timeoutSeconds >= 0 if timeoutSeconds, "timeoutSeconds must be greater than or equal to 0"
periodSeconds >= 0 if periodSeconds, "periodSeconds must be greater than or equal to 0"
successThreshold >= 0 if successThreshold, "successThreshold must be greater than or equal to 0"
failureThreshold >= 0 if failureThreshold, "failureThreshold must be greater than or equal to 0"
terminationGracePeriod >= 0 if terminationGracePeriod, "terminationGracePeriod must be greater than or equal to 0"

schema Exec:
""" Exec describes a "run in container" action.

Attributes
----------
command: [str], default is Undefined, required.
The command line to execute inside the container.

Examples
--------
import kam.core.v1 as v1

execProbe = v1.Exec {
command: ["probe.sh"]
}
"""

# The command line to execute inside the container.
# Exit status of 0 is treated as live/healthy and non-zero is unhealthy.
command: [str]

check:
len(command) > 0, "command must be specified"

schema Http:
""" Http describes an action based on HTTP Get requests.

Attributes
----------
url: str, default is Undefined, required.
The full qualified url to send HTTP requests.
headers: {str:str}, default is Undefined, optional.
Collection of custom headers to set in the request

Examples
--------
import kam.core.v1 as v1

httpProbe = v1.Http {
url: "http://localhost:80"
headers: {
"X-HEADER": "VALUE"
}
}
"""

# The full qualified url to send HTTP requests.
url: str

# Custom headers to set in the request.
headers?: {str:str}

check:
all header in headers {
regex.match(header, r"^[-A-Za-z0-9]+$")
} if headers, "a valid HTTP header must consist of alphanumeric characters or '-' e.g X-Header-Name"

schema Tcp:
""" Tcp describes an action based on opening a socket.

Attributes
----------
url: str, default is Undefined, required.
The full qualified url to open a socket.

Examples
--------
import kam.core.v1 as v1

tcpProbe = v1.Tcp {
url: "tcp://localhost:1234"
}
"""

# The full qualified url to open a socket.
url: str

schema Lifecycle:
""" Lifecycle describes actions that the management system should take in response
to container lifecycle events.

Attributes
----------
preStop: p.Exec | p.Http, default is Undefined, optional.
The action to be taken before a container is terminated due to an API request or
management event such as liveness/startup probe failure, preemption, resource contention, etc.
More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks
postStart: p.Exec | p.Http, default is Undefined, optional.
The action to be taken after a container is created.
More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks

Examples
--------
import kam.core.v1 as v1

lifecycleHook = v1.Lifecycle {
preStop: v1.Exec {
command: ["preStop.sh"]
}
postStart: v1.Http {
url: "http://localhost:80"
}
}
"""

# The action to be taken before a container is terminated.
preStop?: Exec | Http

# The action to be taken after a container is created.
postStart?: Exec | Http
5 changes: 5 additions & 0 deletions core/v1/exclusive_accessory.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
schema ExclusiveAccessory(Accessory):
""" For specific accessory schema definition, if there should be only one instance within AppConfiguration, must
inherit the ExclusiveAccessory schema.
"""

Loading