From 468f6771e4b89cd33a69479a20e59935ccc1f180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Kanngie=C3=9Fer?= <67148147+kanngiesser@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:50:40 +0200 Subject: [PATCH] feat: add validation for allowed OS and Arch combinations (#1103) docs: update description for platform object at brokerpak specification --- docs/brokerpak-specification.md | 10 +++--- internal/brokerpak/manifest/parser_test.go | 38 ++++++++++++++++++++++ internal/brokerpak/platform/platform.go | 37 ++++++++++++++++++--- 3 files changed, 76 insertions(+), 9 deletions(-) diff --git a/docs/brokerpak-specification.md b/docs/brokerpak-specification.md index ee8fe562e..42a8857b3 100644 --- a/docs/brokerpak-specification.md +++ b/docs/brokerpak-specification.md @@ -74,12 +74,12 @@ Fields marked with `*` are required, others are optional. #### Platform object -The platform OS and architecture follow Go's naming scheme. +The platform OS and architecture follow Go's naming scheme. Combinations of OS and architecture for which there is an [OpenTofu release](https://github.com/opentofu/opentofu/releases) are valid. -| Field | Type | Description | Valid Values | -|-------|--------|---------------------------------------|-------------------| -| os* | string | The operating system of the platform. | `linux`, `darwin` | -| arch* | string | The architecture of the platform. | `"386"`, `amd64` | +| Field | Type | Description | Valid Values | +|-------|--------|---------------------------------------|----------------------------------------------------------------| +| os* | string | The operating system of the platform. | `darwin`, `freebsd`, `linux`, `openbsd`, `solaris`, `windows` | +| arch* | string | The architecture of the platform. | `386`, `amd64`, `arm`, `arm64` | Fields marked with `*` are required, others are optional. #### OpenTofu resource object diff --git a/internal/brokerpak/manifest/parser_test.go b/internal/brokerpak/manifest/parser_test.go index bdce6be37..03fc4e464 100644 --- a/internal/brokerpak/manifest/parser_test.go +++ b/internal/brokerpak/manifest/parser_test.go @@ -288,6 +288,44 @@ var _ = Describe("Parser", func() { Entry("arch", "platforms[2].arch", map[string]any{"os": "linux"}), ) + DescribeTable("valid platform object", + func(value platform.Platform) { + m, err := manifest.Parse(fakeManifest(with("platforms", []platform.Platform{value}))) + + Expect(err).To(BeNil()) + Expect(m).ToNot(BeNil()) + }, + + Entry("darwin/amd64", platform.Platform{Os: "darwin", Arch: "amd64"}), + Entry("darwin/arm64", platform.Platform{Os: "darwin", Arch: "arm64"}), + Entry("freebsd/386", platform.Platform{Os: "freebsd", Arch: "386"}), + Entry("freebsd/amd64", platform.Platform{Os: "freebsd", Arch: "amd64"}), + Entry("freebsd/arm", platform.Platform{Os: "freebsd", Arch: "arm"}), + Entry("linux/386", platform.Platform{Os: "linux", Arch: "386"}), + Entry("linux/amd64", platform.Platform{Os: "linux", Arch: "amd64"}), + Entry("linux/arm", platform.Platform{Os: "linux", Arch: "arm"}), + Entry("linux/arm64", platform.Platform{Os: "linux", Arch: "arm64"}), + Entry("openbsd/386", platform.Platform{Os: "openbsd", Arch: "386"}), + Entry("openbsd/amd64", platform.Platform{Os: "openbsd", Arch: "amd64"}), + Entry("solaris/amd64", platform.Platform{Os: "solaris", Arch: "amd64"}), + Entry("windows/386", platform.Platform{Os: "windows", Arch: "386"}), + Entry("windows/amd64", platform.Platform{Os: "windows", Arch: "amd64"}), + ) + + DescribeTable("invalid platform object", + func(value platform.Platform) { + m, err := manifest.Parse(fakeManifest(with("platforms", []platform.Platform{value}))) + + Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("invalid value: %v/%v: platforms[0]", value.Os, value.Arch)))) + Expect(m).To(BeNil()) + }, + + Entry("darwin/386", platform.Platform{Os: "darwin", Arch: "386"}), + Entry("freebsd/arm64", platform.Platform{Os: "freebsd", Arch: "arm64"}), + Entry("linux/amd", platform.Platform{Os: "linux", Arch: "amd"}), + Entry("windows/arm", platform.Platform{Os: "windows", Arch: "arm64"}), + ) + DescribeTable("missing terraform binary data", func(insert string, value map[string]any) { m, err := manifest.Parse(fakeManifest(withAdditionalEntry("terraform_binaries", value))) diff --git a/internal/brokerpak/platform/platform.go b/internal/brokerpak/platform/platform.go index 3bf9b1997..69da5201b 100644 --- a/internal/brokerpak/platform/platform.go +++ b/internal/brokerpak/platform/platform.go @@ -52,12 +52,41 @@ type Platform struct { var _ validation.Validatable = (*Platform)(nil) +// allowed OS/Arch combinations +// +// must be possible value for $GOOS and $GOARCH (https://go.dev/doc/install/source#environment) +// there must be an OpenTofu release for the respective OS/ARCH (see brokerpakurl.go) +var ( + darwinAmd64 = Platform{Os: "darwin", Arch: "amd64"} + darwinArm64 = Platform{Os: "darwin", Arch: "arm64"} + freebsd386 = Platform{Os: "freebsd", Arch: "386"} + freebsdAmd64 = Platform{Os: "freebsd", Arch: "amd64"} + freebsdArm = Platform{Os: "freebsd", Arch: "arm"} + linux386 = Platform{Os: "linux", Arch: "386"} + linuxAmd64 = Platform{Os: "linux", Arch: "amd64"} + linuxArm = Platform{Os: "linux", Arch: "arm"} + linuxArm64 = Platform{Os: "linux", Arch: "arm64"} + openbsd386 = Platform{Os: "openbsd", Arch: "386"} + openbsdAmd64 = Platform{Os: "openbsd", Arch: "amd64"} + solarisAmd64 = Platform{Os: "solaris", Arch: "amd64"} + windows386 = Platform{Os: "windows", Arch: "386"} + windowsAmd64 = Platform{Os: "windows", Arch: "amd64"} +) + // Validate implements validation.Validatable. func (p Platform) Validate() (errs *validation.FieldError) { - return errs.Also( - validation.ErrIfBlank(p.Os, "os"), - validation.ErrIfBlank(p.Arch, "arch"), - ) + + if errs := errs.Also(validation.ErrIfBlank(p.Os, "os"), validation.ErrIfBlank(p.Arch, "arch")); errs != nil { + return errs + } + + switch p { + case darwinAmd64, darwinArm64, freebsd386, freebsdAmd64, freebsdArm, linux386, linuxAmd64, linuxArm, linuxArm64, openbsd386, openbsdAmd64, solarisAmd64, windows386, windowsAmd64: + default: + return validation.ErrInvalidValue(p, "") + } + + return nil } // String formats the platform as an os/arch pair.