Skip to content

Commit

Permalink
Add stuff to use rules_oci with Pulumi.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zemnmez committed Nov 25, 2024
1 parent 1c0cbd8 commit 83dedc0
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 132 deletions.
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ py_venv(
"//py/ibazel:ibazel_bin",
"//py/ipynb",
"//py/ipynb:ipynb_bin",
"//ts/pulumi/lib/oci/example/python:python_bin",
],
)

Expand Down
11 changes: 11 additions & 0 deletions oci/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"Helpers for OCI images."

load("//bzl:rules.bzl", "bazel_lint")

bazel_lint(
name = "bazel_lint",
srcs = [
"BUILD.bazel",
"py_layer.bzl",
],
)
83 changes: 83 additions & 0 deletions oci/py_layer.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
Wrapper macro to make three separate layers for python applications
Originally from: https://github.com/aspect-build/bazel-examples/blob/863f752396a4c400c311927ce21083f2eee38f30/oci_python_image/py_layer.bzl
"""

load("@aspect_bazel_lib//lib:tar.bzl", "mtree_spec", "tar")
load("@rules_oci//oci:defs.bzl", "oci_image")

# match *only* external repositories that have the string "python"
# e.g. this will match
# `/hello_world/hello_world_bin.runfiles/rules_python~0.21.0~python~python3_9_aarch64-unknown-linux-gnu/bin/python3`
# but not match
# `/hello_world/hello_world_bin.runfiles/_main/python_app`
PY_INTERPRETER_REGEX = "\\.runfiles/.*python.*-.*"

# match *only* external pip like repositories that contain the string "site-packages"
SITE_PACKAGES_REGEX = "\\.runfiles/.*/site-packages/.*"

def py_layers(name, binary):
"""Create three layers for a py_binary target: interpreter, third-party dependencies, and application code.
This allows a container image to have smaller uploads, since the application layer usually changes more
than the other two.
Args:
name: prefix for generated targets, to ensure they are unique within the package
binary: a py_binary target
Returns:
a list of labels for the layers, which are tar files
"""

# Produce layers in this order, as the app changes most often
layers = ["interpreter", "packages", "app"]

# Produce the manifest for a tar file of our py_binary, but don't tar it up yet, so we can split
# into fine-grained layers for better docker performance.
mtree_spec(
name = name + ".mf",
srcs = [binary],
)

native.genrule(
name = name + ".interpreter_tar_manifest",
srcs = [name + ".mf"],
outs = [name + ".interpreter_tar_manifest.spec"],
cmd = "grep -v '{}' $< | grep '{}' >$@".format(SITE_PACKAGES_REGEX, PY_INTERPRETER_REGEX),
)

native.genrule(
name = name + ".packages_tar_manifest",
srcs = [name + ".mf"],
outs = [name + ".packages_tar_manifest.spec"],
cmd = "grep '{}' $< >$@".format(SITE_PACKAGES_REGEX),
)

# Any lines that didn't match one of the two grep above
native.genrule(
name = name + ".app_tar_manifest",
srcs = [name + ".mf"],
outs = [name + ".app_tar_manifest.spec"],
cmd = "grep -v '{}' $< | grep -v '{}' >$@".format(SITE_PACKAGES_REGEX, PY_INTERPRETER_REGEX),
)

result = []
for layer in layers:
layer_target = "{}.{}_layer".format(name, layer)
result.append(layer_target)
tar(
name = layer_target,
srcs = [binary],
mtree = "{}.{}_tar_manifest".format(name, layer),
)

return result

def py_oci_image(name, binary, tars = [], **kwargs):
"Wrapper around oci_image that splits the py_binary into layers."
oci_image(
name = name,
tars = tars + py_layers(name, binary),
**kwargs
)
1 change: 0 additions & 1 deletion ts/pulumi/lib/docker/Dockerfile.tmpl

This file was deleted.

81 changes: 0 additions & 81 deletions ts/pulumi/lib/docker/rules.bzl

This file was deleted.

35 changes: 0 additions & 35 deletions ts/pulumi/lib/docker/testing/example/simple/BUILD.bazel

This file was deleted.

8 changes: 0 additions & 8 deletions ts/pulumi/lib/docker/testing/example/simple/main.ts

This file was deleted.

File renamed without changes.
27 changes: 27 additions & 0 deletions ts/pulumi/lib/oci/example/python/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
load("//bzl:rules.bzl", "bazel_lint")
load("//oci:py_layer.bzl", "py_oci_image")
load("//py:rules.bzl", "py_binary")
load("//ts/pulumi/lib/oci:rules.bzl", "pulumi_image")

py_binary(
name = "python_bin",
srcs = ["__main__.py"],
main = "__main__.py",
visibility = ["//:__subpackages__"],
)

py_oci_image(
name = "oci_image",
base = "@distroless_base",
binary = "python_bin",
)

pulumi_image(
name = "example_python_image",
src = ":oci_image",
)

bazel_lint(
name = "bazel_lint",
srcs = ["BUILD.bazel"],
)
1 change: 1 addition & 0 deletions ts/pulumi/lib/oci/example/python/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print("Hello, world!")
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import { Image, ImageArgs } from "@pulumi/awsx/ecr";
import { local } from '@pulumi/command';
import { ComponentResource, ComponentResourceOptions } from "@pulumi/pulumi";


export interface Args {
image: Omit<ImageArgs, 'dockerfile'>
repository: string
}

export class __ClassName extends ComponentResource {
image: Image
constructor(
name: string,
args: Args,
opts?: ComponentResourceOptions
) {
super('__TYPE', name, args, opts);

this.image = new Image(`${name}_image`, {
dockerfile: '__DOCKERFILE_PATH',
...args.image
const upload = new local.Command(`${name}_push`, {
create: [
"__PUSH_BIN",
"--repository",
args.repository,
].join(" ")
}, { parent: this })


super.registerOutputs({ image: this.image })
super.registerOutputs({ upload })
}


Expand Down
65 changes: 65 additions & 0 deletions ts/pulumi/lib/oci/rules.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"Push an OCI image with Pulumi."

load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template_rule")
load("@rules_oci//oci:defs.bzl", "oci_push")
load("//ts:rules.bzl", "ts_project")

def pulumi_image(
name,
src,
component_name = None,
out = None,
visibility = None):
"""
Generate Pulumi component to push a container image to a repo.
Args:
name: name of the resulting ts_project module.
src: content of the OCI image.
component_name: name of the exported pulumi class
out: ts filename (defaults to ${component_name}.ts)
visibility: bazel visibility
"""

if component_name == None:
component_name = "".join([
segment.capitalize()
for segment in name.split("_")
])

if out == None:
out = component_name + ".ts"

oci_push(
name = name + "_push_bin",
image = src,
repository = "why is this mandatory",
)

expand_template_rule(
name = name + "_tsfiles",
template = "//ts/pulumi/lib/oci:oci_image.tmpl.ts",
out = out,
data = [
":" + name + "_push_bin",
],
substitutions = {
"__ClassName": component_name,
"__TYPE": native.package_name().replace("/", ":"),
"__PUSH_BIN": "$(rootpath :" + name + "_push_bin" + ")",
},
)

ts_project(
name = name,
srcs = [name + "_tsfiles"],
data = [
":" + name + "_push_bin",
],
deps = [
"//:node_modules/@pulumi/pulumi",
"//:node_modules/@pulumi/command",
"//:node_modules/@types/node",
],
visibility = visibility,
)

0 comments on commit 83dedc0

Please sign in to comment.