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

Add --hosts-file flag; Add nohosts to remote build APIs #21062

Merged
merged 2 commits into from
Nov 25, 2024
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
7 changes: 7 additions & 0 deletions cmd/podman/common/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,13 @@ func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string)
return getNetworks(cmd, toComplete, completeDefault)
}

// AutocompleteHostsFile - Autocomplete hosts file options.
// -> "image", "none", paths
func AutocompleteHostsFile(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
hostsFileModes := []string{"image", "none"}
return hostsFileModes, cobra.ShellCompDirectiveDefault
}

// AutocompleteDefaultOneArg - Autocomplete path only for the first argument.
func AutocompleteDefaultOneArg(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
Expand Down
14 changes: 14 additions & 0 deletions cmd/podman/common/netflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ func DefineNetFlags(cmd *cobra.Command) {
)
_ = cmd.RegisterFlagCompletionFunc(addHostFlagName, completion.AutocompleteNone)

hostsFileFlagName := "hosts-file"
netFlags.String(
hostsFileFlagName, "",
`Base file to create the /etc/hosts file inside the container, or one of the special values. ("image"|"none")`,
)
_ = cmd.RegisterFlagCompletionFunc(hostsFileFlagName, AutocompleteHostsFile)

dnsFlagName := "dns"
netFlags.StringSlice(
dnsFlagName, podmanConfig.ContainersConf.DNSServers(),
Expand Down Expand Up @@ -116,6 +123,13 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
}
}

if flags.Changed("hosts-file") {
opts.HostsFile, err = flags.GetString("hosts-file")
if err != nil {
return nil, err
}
}

if flags.Changed("dns") {
servers, err := flags.GetStringSlice("dns")
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions cmd/podman/containers/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
if noHosts && c.Flag("add-host").Changed {
return vals, errors.New("--no-hosts and --add-host cannot be set together")
}
if noHosts && c.Flag("hosts-file").Changed {
return vals, errors.New("--no-hosts and --hosts-file cannot be set together")
}

if !isInfra && c.Flag("entrypoint").Changed {
val := c.Flag("entrypoint").Value.String()
Expand Down
1 change: 1 addition & 0 deletions cmd/podman/pods/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ func create(cmd *cobra.Command, args []string) error {
}
podSpec.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
podSpec.InfraContainerSpec.RawImageName = rawImageName
podSpec.InfraContainerSpec.BaseHostsFile = podSpec.PodNetworkConfig.HostsFile
podSpec.InfraContainerSpec.NetworkOptions = podSpec.NetworkOptions
podSpec.InfraContainerSpec.RestartPolicy = podSpec.RestartPolicy
err = specgenutil.FillOutSpecGen(podSpec.InfraContainerSpec, &infraOptions, []string{})
Expand Down
12 changes: 12 additions & 0 deletions docs/source/markdown/options/hosts-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
####> This option file is used in:
####> podman create, pod create, run
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--hosts-file**=*path* | *none* | *image*

Base file to create the `/etc/hosts` file inside the container. This must either
be an absolute path to a file on the host system, or one of the following
special flags:
"" Follow the `base_hosts_file` configuration in _containers.conf_ (the default)
`none` Do not use a base file (i.e. start with an empty file)
`image` Use the container image's `/etc/hosts` file as base file
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-create.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ Print usage statement

@@option hostname.container

@@option hosts-file

@@option hostuser

@@option http-proxy
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-pod-create.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ Print usage statement.

@@option hostname.pod

@@option hosts-file

#### **--infra**

Create an infra container and associate it with the pod. An infra container is a lightweight container used to coordinate the shared kernel namespace of a pod. Default: true.
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-run.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ Print usage statement

@@option hostname.container

@@option hosts-file

@@option hostuser

@@option http-proxy
Expand Down
9 changes: 4 additions & 5 deletions libpod/container_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,10 @@ type ContainerNetworkConfig struct {
// bind-mounted inside the container.
// Conflicts with HostAdd.
UseImageHosts bool
// BaseHostsFile is the path to a hosts file, the entries from this file
// are added to the containers hosts file. As special value "image" is
// allowed which uses the /etc/hosts file from within the image and "none"
// which uses no base file at all. If it is empty we should default
// to the base_hosts_file configuration in containers.conf.
// BaseHostsFile is the base file to create the `/etc/hosts` file inside the container.
// This must either be an absolute path to a file on the host system, or one of the
// special flags `image` or `none`.
// If it is empty it defaults to the base_hosts_file configuration in containers.conf.
BaseHostsFile string `json:"baseHostsFile,omitempty"`
// Hosts to add in container
// Will be appended to host's host file
Expand Down
2 changes: 2 additions & 0 deletions libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
hostConfig.GroupAdd = make([]string, 0, len(c.config.Groups))
hostConfig.GroupAdd = append(hostConfig.GroupAdd, c.config.Groups...)

hostConfig.HostsFile = c.config.BaseHostsFile

if ctrSpec.Process != nil {
if ctrSpec.Process.OOMScoreAdj != nil {
hostConfig.OomScoreAdj = *ctrSpec.Process.OOMScoreAdj
Expand Down
2 changes: 2 additions & 0 deletions libpod/define/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ type InspectContainerHostConfig struct {
// ExtraHosts contains hosts that will be added to the container's
// /etc/hosts.
ExtraHosts []string `json:"ExtraHosts"`
// HostsFile is the base file to create the `/etc/hosts` file inside the container.
HostsFile string `json:"HostsFile"`
// GroupAdd contains groups that the user inside the container will be
// added to.
GroupAdd []string `json:"GroupAdd"`
Expand Down
3 changes: 3 additions & 0 deletions libpod/define/pod_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ type InspectPodInfraConfig struct {
// HostAdd adds a number of hosts to the infra container's resolv.conf
// which will be shared with the rest of the pod.
HostAdd []string
// HostsFile is the base file to create the `/etc/hosts` file inside the infra container
// which will be shared with the rest of the pod.
HostsFile string
// Networks is a list of networks the pod will join.
Networks []string
// NetworkOptions are additional options for each network
Expand Down
3 changes: 3 additions & 0 deletions libpod/pod_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,9 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
infraConfig.HostAdd = make([]string, 0, len(infra.config.HostAdd))
infraConfig.HostAdd = append(infraConfig.HostAdd, infra.config.HostAdd...)
}
if len(infra.config.BaseHostsFile) > 0 {
infraConfig.HostsFile = infra.config.BaseHostsFile
}

networks, err := infra.networks()
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/handlers/compat/images_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Memory int64 `schema:"memory"`
NamespaceOptions string `schema:"nsoptions"`
NoCache bool `schema:"nocache"`
NoHosts bool `schema:"nohosts"`
OmitHistory bool `schema:"omithistory"`
OSFeatures []string `schema:"osfeature"`
OSVersion string `schema:"osversion"`
Expand Down Expand Up @@ -720,6 +721,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
LabelOpts: labelOpts,
Memory: query.Memory,
MemorySwap: query.MemSwap,
NoHosts: query.NoHosts,
OmitHistory: query.OmitHistory,
SeccompProfilePath: seccomp,
ShmSize: strconv.Itoa(query.ShmSize),
Expand Down
12 changes: 12 additions & 0 deletions pkg/api/server/register_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// TBD Extra hosts to add to /etc/hosts
// (As of version 1.xx)
// - in: query
// name: nohosts
// type: boolean
// default:
// description: |
// Not to create /etc/hosts when building the image
// - in: query
// name: remote
// type: string
// default:
Expand Down Expand Up @@ -1502,6 +1508,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// TBD Extra hosts to add to /etc/hosts
// (As of version 1.xx)
// - in: query
// name: nohosts
// type: boolean
// default:
// description: |
// Not to create /etc/hosts when building the image
// - in: query
// name: remote
// type: string
// default:
Expand Down
3 changes: 3 additions & 0 deletions pkg/bindings/images/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,9 @@ func Build(ctx context.Context, containerFiles []string, options types.BuildOpti
if options.NoCache {
params.Set("nocache", "1")
}
if options.CommonBuildOpts.NoHosts {
params.Set("nohosts", "1")
}
if t := options.Output; len(t) > 0 {
params.Set("output", t)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/entities/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ func ToPodSpecGen(s specgen.PodSpecGenerator, p *PodCreateOptions) (*specgen.Pod
s.DNSOption = p.Net.DNSOptions
s.NoManageHosts = p.Net.NoHosts
s.HostAdd = p.Net.AddHosts
s.HostsFile = p.Net.HostsFile
}

// Cgroup
Expand Down
1 change: 1 addition & 0 deletions pkg/domain/entities/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type NetOptions struct {
DNSOptions []string `json:"dns_option,omitempty"`
DNSSearch []string `json:"dns_search,omitempty"`
DNSServers []net.IP `json:"dns_server,omitempty"`
HostsFile string `json:"hosts_file,omitempty"`
Network specgen.Namespace `json:"netns,omitempty"`
NoHosts bool `json:"no_manage_hosts,omitempty"`
PublishPorts []types.PortMapping `json:"portmappings,omitempty"`
Expand Down
3 changes: 3 additions & 0 deletions pkg/specgen/generate/pod_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
if len(p.HostAdd) > 0 {
spec.HostAdd = p.HostAdd
}
if len(p.HostsFile) > 0 {
spec.BaseHostsFile = p.HostsFile
}
if len(p.DNSServer) > 0 {
var dnsServers []net.IP
dnsServers = append(dnsServers, p.DNSServer...)
Expand Down
12 changes: 10 additions & 2 deletions pkg/specgen/pod_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ func (p *PodSpecGenerator) Validate() error {
if len(p.HostAdd) > 0 {
return exclusivePodOptions("NoInfra", "HostAdd")
}
if len(p.HostsFile) > 0 {
return exclusivePodOptions("NoInfra", "HostsFile")
}
if p.NoManageResolvConf {
return exclusivePodOptions("NoInfra", "NoManageResolvConf")
}
Expand All @@ -79,8 +82,13 @@ func (p *PodSpecGenerator) Validate() error {
return exclusivePodOptions("NoManageResolvConf", "DNSOption")
}
}
if p.NoManageHosts && len(p.HostAdd) > 0 {
return exclusivePodOptions("NoManageHosts", "HostAdd")
if p.NoManageHosts {
if len(p.HostAdd) > 0 {
return exclusivePodOptions("NoManageHosts", "HostAdd")
}
if len(p.HostsFile) > 0 {
return exclusivePodOptions("NoManageHosts", "HostsFile")
}
}

return nil
Expand Down
7 changes: 7 additions & 0 deletions pkg/specgen/podspecgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ type PodNetworkConfig struct {
// Conflicts with NoInfra=true and NoManageHosts.
// Optional.
HostAdd []string `json:"hostadd,omitempty"`
// HostsFile is the base file to create the `/etc/hosts` file inside the infra container.
// This must either be an absolute path to a file on the host system, or one of the
// special flags `image` or `none`.
// If it is empty it defaults to the base_hosts_file configuration in containers.conf.
// Conflicts with NoInfra=true and NoManageHosts.
// Optional.
HostsFile string `json:"hostsFile,omitempty"`
// NetworkOptions are additional options for each network
// Optional.
NetworkOptions map[string][]string `json:"network_options,omitempty"`
Expand Down
9 changes: 4 additions & 5 deletions pkg/specgen/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,11 +539,10 @@ type ContainerNetworkConfig struct {
// Conflicts with HostAdd.
// Optional.
UseImageHosts *bool `json:"use_image_hosts,omitempty"`
// BaseHostsFile is the path to a hosts file, the entries from this file
// are added to the containers hosts file. As special value "image" is
// allowed which uses the /etc/hosts file from within the image and "none"
// which uses no base file at all. If it is empty we should default
// to the base_hosts_file configuration in containers.conf.
// BaseHostsFile is the base file to create the `/etc/hosts` file inside the container.
// This must either be an absolute path to a file on the host system, or one of the
// special flags `image` or `none`.
// If it is empty it defaults to the base_hosts_file configuration in containers.conf.
// Optional.
BaseHostsFile string `json:"base_hosts_file,omitempty"`
// HostAdd is a set of hosts which will be added to the container's
Expand Down
1 change: 1 addition & 0 deletions pkg/specgenutil/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions

if c.Net != nil {
s.HostAdd = c.Net.AddHosts
s.BaseHostsFile = c.Net.HostsFile
s.UseImageResolvConf = &c.Net.UseImageResolvConf
s.DNSServers = c.Net.DNSServers
s.DNSSearch = c.Net.DNSSearch
Expand Down
25 changes: 25 additions & 0 deletions test/e2e/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,31 @@ RUN [[ -L /test/dummy-symlink ]] && echo SYMLNKOK || echo SYMLNKERR`, CITEST_IMA
Expect(session.OutputToString()).To(ContainSubstring("SYMLNKOK"))
})

It("podman build --no-hosts", func() {
targetPath := podmanTest.TempDir

containerFile := filepath.Join(targetPath, "Containerfile")
content := `FROM scratch
RUN echo '56.78.12.34 image.example.com' > /etc/hosts`

Expect(os.WriteFile(containerFile, []byte(content), 0755)).To(Succeed())

defer func() {
Expect(os.RemoveAll(containerFile)).To(Succeed())
}()

session := podmanTest.Podman([]string{
"build", "--pull-never", "-t", "hosts_test", "--no-hosts", "--from", CITEST_IMAGE, targetPath,
})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())

session = podmanTest.Podman([]string{"run", "--no-hosts", "--rm", "hosts_test", "cat", "/etc/hosts"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
Expect(session.OutputToString()).To(Equal("56.78.12.34 image.example.com"))
})

It("podman build --from, --add-host, --cap-drop, --cap-add", func() {
targetPath := podmanTest.TempDir

Expand Down
13 changes: 8 additions & 5 deletions test/e2e/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,14 +663,14 @@ func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSe

// BuildImage uses podman build and buildah to build an image
// called imageName based on a string dockerfile
func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) string {
return p.buildImage(dockerfile, imageName, layers, "")
func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string, extraOptions ...string) string {
return p.buildImage(dockerfile, imageName, layers, "", extraOptions)
}

// BuildImageWithLabel uses podman build and buildah to build an image
// called imageName based on a string dockerfile, adds desired label to paramset
func (p *PodmanTestIntegration) BuildImageWithLabel(dockerfile, imageName string, layers string, label string) string {
return p.buildImage(dockerfile, imageName, layers, label)
func (p *PodmanTestIntegration) BuildImageWithLabel(dockerfile, imageName string, layers string, label string, extraOptions ...string) string {
return p.buildImage(dockerfile, imageName, layers, label, extraOptions)
}

// PodmanPID execs podman and returns its PID
Expand Down Expand Up @@ -1299,7 +1299,7 @@ func (s *PodmanSessionIntegration) jq(jqCommand string) (string, error) {
return strings.TrimRight(out.String(), "\n"), err
}

func (p *PodmanTestIntegration) buildImage(dockerfile, imageName string, layers string, label string) string {
func (p *PodmanTestIntegration) buildImage(dockerfile, imageName string, layers string, label string, extraOptions []string) string {
dockerfilePath := filepath.Join(p.TempDir, "Dockerfile-"+stringid.GenerateRandomID())
err := os.WriteFile(dockerfilePath, []byte(dockerfile), 0755)
Expect(err).ToNot(HaveOccurred())
Expand All @@ -1310,6 +1310,9 @@ func (p *PodmanTestIntegration) buildImage(dockerfile, imageName string, layers
if len(imageName) > 0 {
cmd = append(cmd, []string{"-t", imageName}...)
}
if len(extraOptions) > 0 {
cmd = append(cmd, extraOptions...)
}
cmd = append(cmd, p.TempDir)
session := p.Podman(cmd)
session.Wait(240)
Expand Down
Loading