Skip to content

Commit aee82a8

Browse files
feat: added a mac-address flag to build option to set the value to the docker config
Signed-off-by: Parthiba-Hazra <[email protected]>
1 parent a51140e commit aee82a8

File tree

7 files changed

+81
-0
lines changed

7 files changed

+81
-0
lines changed

internal/build/fakes/fake_builder.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,9 @@ func WithBuilder(builder *FakeBuilder) func(*build.LifecycleOptions) {
122122
opts.Builder = builder
123123
}
124124
}
125+
126+
func WithMacAddresss(mac_addresss string) func(*build.LifecycleOptions) {
127+
return func(opts *build.LifecycleOptions) {
128+
opts.MacAddress = mac_addresss
129+
}
130+
}

internal/build/lifecycle_executor.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ type LifecycleOptions struct {
9797
Workspace string
9898
GID int
9999
UID int
100+
MacAddress string
100101
PreviousImage string
101102
ReportDestinationDir string
102103
SBOMDestinationDir string

internal/build/phase_config_provider.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ func NewPhaseConfigProvider(name string, lifecycleExec *LifecycleExecution, ops
4646
provider.ctrConf.Image = lifecycleExec.opts.Builder.Name()
4747
provider.ctrConf.Labels = map[string]string{"author": "pack"}
4848

49+
if lifecycleExec.opts.MacAddress != "" {
50+
provider.ctrConf.MacAddress = lifecycleExec.opts.MacAddress
51+
lifecycleExec.logger.Debugf("MAC Address: %s", style.Symbol(lifecycleExec.opts.MacAddress))
52+
}
53+
4954
if lifecycleExec.os == "windows" {
5055
provider.hostConf.Isolation = container.IsolationProcess
5156
}

internal/build/phase_config_provider_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ func testPhaseConfigProvider(t *testing.T, when spec.G, it spec.S) {
7575
})
7676
})
7777

78+
when("mac address is set", func() {
79+
it("should set MacAddress in LifecycleOptions", func() {
80+
expectedMacAddress := "01:23:45:67:89:ab"
81+
lifecycle := newTestLifecycleExec(t, false, "some-temp-dir", fakes.WithMacAddresss(expectedMacAddress))
82+
83+
phaseConfigProvider := build.NewPhaseConfigProvider("some-name", lifecycle)
84+
85+
h.AssertEq(t, phaseConfigProvider.ContainerConfig().MacAddress, expectedMacAddress)
86+
})
87+
})
88+
7889
when("building with interactive mode", func() {
7990
it("returns a phase config provider with interactive args", func() {
8091
handler := func(bodyChan <-chan container.WaitResponse, errChan <-chan error, reader io.Reader) error {

internal/commands/build.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package commands
33
import (
44
"os"
55
"path/filepath"
6+
"regexp"
67
"strconv"
78
"strings"
89
"time"
@@ -49,6 +50,7 @@ type BuildFlags struct {
4950
Workspace string
5051
GID int
5152
UID int
53+
MacAddress string
5254
PreviousImage string
5355
SBOMDestinationDir string
5456
ReportDestinationDir string
@@ -57,6 +59,8 @@ type BuildFlags struct {
5759
PostBuildpacks []string
5860
}
5961

62+
var macAddressRegex = regexp.MustCompile(`^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$`)
63+
6064
// Build an image from source code
6165
func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cobra.Command {
6266
var flags BuildFlags
@@ -185,6 +189,7 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob
185189
LifecycleImage: lifecycleImage,
186190
GroupID: gid,
187191
UserID: uid,
192+
MacAddress: flags.MacAddress,
188193
PreviousImage: inputPreviousImage.Name(),
189194
Interactive: flags.Interactive,
190195
SBOMDestinationDir: flags.SBOMDestinationDir,
@@ -266,6 +271,7 @@ This option may set DOCKER_HOST environment variable for the build container if
266271
cmd.Flags().StringVar(&buildFlags.Workspace, "workspace", "", "Location at which to mount the app dir in the build image")
267272
cmd.Flags().IntVar(&buildFlags.GID, "gid", 0, `Override GID of user's group in the stack's build and run images. The provided value must be a positive number`)
268273
cmd.Flags().IntVar(&buildFlags.UID, "uid", 0, `Override UID of user in the stack's build and run images. The provided value must be a positive number`)
274+
cmd.Flags().StringVar(&buildFlags.MacAddress, "mac-address", "", "MAC address to set for the build container network configuration")
269275
cmd.Flags().StringVar(&buildFlags.PreviousImage, "previous-image", "", "Set previous image to a particular tag reference, digest reference, or (when performing a daemon build) image ID")
270276
cmd.Flags().StringVar(&buildFlags.SBOMDestinationDir, "sbom-output-dir", "", "Path to export SBoM contents.\nOmitting the flag will yield no SBoM content.")
271277
cmd.Flags().StringVar(&buildFlags.ReportDestinationDir, "report-output-dir", "", "Path to export build report.toml.\nOmitting the flag yield no report file.")
@@ -306,6 +312,10 @@ func validateBuildFlags(flags *BuildFlags, cfg config.Config, inputImageRef clie
306312
return errors.New("uid flag must be in the range of 0-2147483647")
307313
}
308314

315+
if flags.MacAddress != "" && !isValidMacAddress(flags.MacAddress) {
316+
return errors.New("invalid MAC address provided")
317+
}
318+
309319
if flags.Interactive && !cfg.Experimental {
310320
return client.NewExperimentError("Interactive mode is currently experimental.")
311321
}
@@ -380,3 +390,7 @@ func parseProjectToml(appPath, descriptorPath string) (projectTypes.Descriptor,
380390
descriptor, err := project.ReadProjectDescriptor(actualPath)
381391
return descriptor, actualPath, err
382392
}
393+
394+
func isValidMacAddress(macAddress string) bool {
395+
return macAddressRegex.MatchString(macAddress)
396+
}

internal/commands/build_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,37 @@ builder = "my-builder"
763763
})
764764
})
765765

766+
when("mac-address flag is provided", func() {
767+
when("mac-address is a valid value", func() {
768+
it("should set MacAddress in BuildOptions", func() {
769+
mockClient.EXPECT().
770+
Build(gomock.Any(), EqBuildOptionsWithMacAddress("01:23:45:67:89:ab")).
771+
Return(nil)
772+
773+
command.SetArgs([]string{"--builder", "my-builder", "image", "--mac-address", "01:23:45:67:89:ab"})
774+
h.AssertNil(t, command.Execute())
775+
})
776+
})
777+
when("mac-address is an invalid value", func() {
778+
it("should throw an error", func() {
779+
command.SetArgs([]string{"--builder", "my-builder", "image", "--mac-address", "invalid-mac"})
780+
err := command.Execute()
781+
h.AssertError(t, err, "invalid MAC address")
782+
})
783+
})
784+
})
785+
786+
when("mac-address flag is not provided", func() {
787+
it("should not set MacAddress in BuildOptions", func() {
788+
mockClient.EXPECT().
789+
Build(gomock.Any(), EqBuildOptionsWithMacAddress("")).
790+
Return(nil)
791+
792+
command.SetArgs([]string{"--builder", "my-builder", "image"})
793+
h.AssertNil(t, command.Execute())
794+
})
795+
})
796+
766797
when("previous-image flag is provided", func() {
767798
when("image is invalid", func() {
768799
it("error must be thrown", func() {
@@ -1076,6 +1107,15 @@ func EqBuildOptionsWithOverrideGroupID(gid int) gomock.Matcher {
10761107
}
10771108
}
10781109

1110+
func EqBuildOptionsWithMacAddress(macAddress string) gomock.Matcher {
1111+
return buildOptionsMatcher{
1112+
description: fmt.Sprintf("MacAddress=%s", macAddress),
1113+
equals: func(o client.BuildOptions) bool {
1114+
return o.MacAddress == macAddress
1115+
},
1116+
}
1117+
}
1118+
10791119
func EqBuildOptionsWithPreviousImage(prevImage string) gomock.Matcher {
10801120
return buildOptionsMatcher{
10811121
description: fmt.Sprintf("Previous image=%s", prevImage),

pkg/client/build.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ type BuildOptions struct {
204204
// Directory to output the report.toml metadata artifact
205205
ReportDestinationDir string
206206

207+
// For storing the mac-address to later pass on docker config structure
208+
MacAddress string
209+
207210
// Desired create time in the output image config
208211
CreationTime *time.Time
209212

@@ -543,6 +546,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error {
543546
Workspace: opts.Workspace,
544547
GID: opts.GroupID,
545548
UID: opts.UserID,
549+
MacAddress: opts.MacAddress,
546550
PreviousImage: opts.PreviousImage,
547551
Interactive: opts.Interactive,
548552
Termui: termui.NewTermui(imageName, ephemeralBuilder, runImageName),

0 commit comments

Comments
 (0)