Skip to content
Merged
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
9 changes: 8 additions & 1 deletion aws_lambda_builders/workflows/go_modules/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class GoModulesBuilder(object):

LANGUAGE = "go"

def __init__(self, osutils, binaries, mode=BuildMode.RELEASE, architecture=X86_64):
def __init__(self, osutils, binaries, mode=BuildMode.RELEASE, architecture=X86_64, trim_go_path=False):
"""Initialize a GoModulesBuilder.

:type osutils: :class:`lambda_builders.utils.OSUtils`
Expand All @@ -33,11 +33,15 @@ def __init__(self, osutils, binaries, mode=BuildMode.RELEASE, architecture=X86_6

:type architecture: str
:param architecture: name of the type of architecture

:type trim_go_path: bool
:param trim_go_path: should go build use -trimpath flag
"""
self.osutils = osutils
self.binaries = binaries
self.mode = mode
self.goarch = get_goarch(architecture)
self.trim_go_path = trim_go_path

def build(self, source_dir_path, output_path):
"""Builds a go project onto an output path.
Expand All @@ -53,6 +57,9 @@ def build(self, source_dir_path, output_path):
env.update({"GOOS": "linux", "GOARCH": self.goarch})
runtime_path = self.binaries[self.LANGUAGE].binary_path
cmd = [runtime_path, "build"]
if self.trim_go_path:
LOG.debug("Trimpath requested: Setting go build configuration to -trimpath")
cmd += ["-trimpath"]
if self.mode and self.mode.lower() == BuildMode.DEBUG:
LOG.debug("Debug build requested: Setting configuration to Debug")
cmd += ["-gcflags", "all=-N -l"]
Expand Down
5 changes: 4 additions & 1 deletion aws_lambda_builders/workflows/go_modules/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ def __init__(

options = kwargs.get("options") or {}
handler = options.get("artifact_executable_name", None)
trim_go_path = options.get("trim_go_path", False)

output_path = osutils.joinpath(artifacts_dir, handler)

builder = GoModulesBuilder(osutils, binaries=self.binaries, mode=mode, architecture=self.architecture)
builder = GoModulesBuilder(
osutils, binaries=self.binaries, mode=mode, architecture=self.architecture, trim_go_path=trim_go_path
)
self.actions = [GoModulesBuildAction(source_dir, output_path, builder)]

def get_validators(self):
Expand Down
68 changes: 67 additions & 1 deletion tests/integration/workflows/go_modules/test_go.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from aws_lambda_builders.exceptions import WorkflowFailedError

from tests.integration.workflows.go_modules.utils import get_executable_arch
from tests.integration.workflows.go_modules.utils import get_md5_hexdigest


class TestGoWorkflow(TestCase):
Expand Down Expand Up @@ -112,6 +113,71 @@ def test_builds_arm64_architecture(self):
options={"artifact_executable_name": "no-deps-main-arm64"},
architecture="arm64",
)

pathname = Path(self.artifacts_dir, "no-deps-main-arm64")
self.assertEqual(get_executable_arch(pathname), "AArch64")

def test_builds_with_trimpath(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a test to show the difference between when trim path is enabled vs not enabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sriram-mv @mndeveci I have added this test case. I wrote a utility that will return the md5 hexdigest of the built binaries. I created a copy of the no-deps go project in testdata. By building an exact copy of that project with -trimpath enabled we can assert that their md5 hex digests are the same. Similarly, we can assert that they will not be equal without the -trimpath flag. This was the most straightforward way that I could think of. Hopefully it is sufficient.

source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
built_trimpath = self.builder.build(
source_dir,
self.artifacts_dir,
self.scratch_dir,
os.path.join(source_dir, "go.mod"),
runtime=self.runtime,
options={"artifact_executable_name": "no-deps-main-trimpath", "trim_go_path": True},
architecture="x86_64",
)
pathname = Path(self.artifacts_dir, "no-deps-main-trimpath")
self.assertEqual(get_executable_arch(pathname), "x64")

def test_builds_without_trimpath_are_not_equal(self):
source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
built_no_trimpath = self.builder.build(
source_dir,
self.artifacts_dir,
self.scratch_dir,
os.path.join(source_dir, "go.mod"),
runtime=self.runtime,
options={"artifact_executable_name": "no-deps-main", "trim_go_path": False},
architecture="x86_64",
)

source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps-copy")
built_no_trimpath_copy = self.builder.build(
source_dir,
self.artifacts_dir,
self.scratch_dir,
os.path.join(source_dir, "go.mod"),
runtime=self.runtime,
options={"artifact_executable_name": "no-deps-main-copy", "trim_go_path": False},
architecture="x86_64",
)
pathname = Path(self.artifacts_dir, "no-deps-main")
pathnameOfCopy = Path(self.artifacts_dir, "no-deps-main-copy")
self.assertNotEqual(get_md5_hexdigest(pathname), get_md5_hexdigest(pathnameOfCopy))

def test_builds_with_trimpath_are_equal(self):
source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
built_with_trimpath = self.builder.build(
source_dir,
self.artifacts_dir,
self.scratch_dir,
os.path.join(source_dir, "go.mod"),
runtime=self.runtime,
options={"artifact_executable_name": "no-deps-main", "trim_go_path": True},
architecture="x86_64",
)

source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps-copy")
built_with_trimpath_copy = self.builder.build(
source_dir,
self.artifacts_dir,
self.scratch_dir,
os.path.join(source_dir, "go.mod"),
runtime=self.runtime,
options={"artifact_executable_name": "no-deps-main-copy", "trim_go_path": True},
architecture="x86_64",
)
pathname = Path(self.artifacts_dir, "no-deps-main")
pathnameOfCopy = Path(self.artifacts_dir, "no-deps-main-copy")
self.assertEqual(get_md5_hexdigest(pathname), get_md5_hexdigest(pathnameOfCopy))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module github.com/awslabs/aws-lambda-builders
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package main

func main() {
}
20 changes: 20 additions & 0 deletions tests/integration/workflows/go_modules/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from elftools.elf.elffile import ELFFile
import hashlib


def get_executable_arch(path):
Expand All @@ -18,3 +19,22 @@ def get_executable_arch(path):
with open(str(path), "rb") as f:
e = ELFFile(f)
return e.get_machine_arch()


def get_md5_hexdigest(path):
"""
Returns the hexdigest of a binary

Parameters
----------
path : str
path to the Go binaries generated

Returns
-------
str
Hex digest of the binaries
"""
with open(str(path), "rb") as f:
hashed = hashlib.md5(f.read())
return hashed.hexdigest()
11 changes: 11 additions & 0 deletions tests/unit/workflows/go_modules/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ def test_debug_configuration_set(self):
stdout="PIPE",
)

def test_trimpath_configuration_set(self):
self.under_test = GoModulesBuilder(self.osutils, self.binaries, "release", "x86_64", True)
self.under_test.build("source_dir", "output_path")
self.osutils.popen.assert_called_with(
["/path/to/go", "build", "-trimpath", "-o", "output_path", "source_dir"],
cwd="source_dir",
env={"GOOS": "linux", "GOARCH": "amd64"},
stderr="PIPE",
stdout="PIPE",
)

def test_debug_configuration_set_with_arm_architecture(self):
self.under_test = GoModulesBuilder(self.osutils, self.binaries, "Debug", "arm64")
self.under_test.build("source_dir", "output_path")
Expand Down