Documentation
¶
Overview ¶
Package ir holds the normalised model that rules operate on.
Both compose files and native Quadlet units parse into this model, so a rule never learns which produced it. That is what lets "audit what you converted" and "audit what you hand-wrote" be the same code path.
The subject of a rule is a Project, not a Unit. Several rules cannot be answered from one unit alone: whether a bind source is shared between units (QD001 and QD002), whether sibling containers can resolve each other (QD030), whether a name collides (QD032). Making Project the subject from the start avoids retrofitting it later. See docs/spec-review.md finding F3.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Mount ¶
type Mount struct {
// Source is the host path or volume name, empty for anonymous mounts.
Source string
// Destination is the path inside the container.
Destination string
// Options are the comma-separated options after the second colon,
// e.g. `ro`, `Z`, `z`, `U`.
Options []string
Type MountType
// UnitRef is the referenced Quadlet unit for a `foo.volume` source,
// otherwise empty.
UnitRef string
// Line is where this mount was declared, for citing in findings.
Line int
// Raw is the original value, so a fix can rewrite it precisely.
Raw string
}
Mount is one `Volume=` entry, decomposed.
func ParseMount ¶
ParseMount decomposes one `Volume=` value.
The grammar is `[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]` (podman-systemd.unit(5)). A source that ends in `.volume` refers to a sibling Quadlet unit, which Podman materialises as a volume named `systemd-$name`.
func (Mount) HasOption ¶
HasOption reports whether an option is present, case-sensitively. Case matters here: `:z` and `:Z` mean different things, shared versus private relabelling, and conflating them is the bug QD002 exists to catch.
func (Mount) HasSELinuxLabel ¶
HasSELinuxLabel reports whether either relabelling option is present.
func (Mount) VolumeObjectName ¶
VolumeObjectName returns the Podman volume name a named-volume source resolves to. Quadlet prefixes volumes it creates with `systemd-`, so `pg.volume` becomes `systemd-pg`. Verified against Podman 5.8.4.
type MountType ¶
type MountType string
MountType distinguishes a host path from a Podman-managed named volume, because the rules that apply differ sharply between them.
const ( // MountBind is a host directory or file mounted into the container. // SELinux relabelling rules apply. MountBind MountType = "bind" // MountNamed is a Podman named volume, including the `foo.volume` form // that refers to a sibling Quadlet unit. MountNamed MountType = "named" // MountAnonymous is a mount with no source, e.g. `Volume=/data`. MountAnonymous MountType = "anonymous" )
type Port ¶
type Port struct {
HostIP string
HostPort int
ContainerPort int
Protocol string
Line int
Raw string
}
Port is one `PublishPort=` entry, decomposed.
type Project ¶
type Project struct {
// Root is the directory the units came from, for reporting.
Root string
// Units are the project's units in a deterministic order.
Units []*Unit
}
Project is a set of units considered together: the subject of every rule.
func LoadProject ¶
LoadProject reads every Quadlet unit under root into a project.
Files whose extension is not a Quadlet unit type are ignored, so pointing quaddoc at a directory containing a README or a compose file is harmless.
func (*Project) BindSourceUsage ¶
BindSourceUsage counts, for every bind-mount source in the project, how many distinct units mount it.
This is computed once and shared, which is what keeps QD001 and QD002 from contradicting each other: QD001 fires only when no relabelling option is present, QD002 only when `:Z` is used on a source this map shows is shared. Deriving sharing independently in each rule would let a fix from one produce a finding from the other. See docs/spec-review.md finding F3.
func (*Project) Containers ¶
Containers returns just the container units.
func (*Project) NamedVolumeUsers ¶
NamedVolumeUsers returns, for each named volume, the units that mount it. QD012 needs this to tell whether a volume a non-root container mounts was previously initialised by a root one.
type SourceEntry ¶
SourceEntry is one assignment as it appeared in the file.
type SourceFile ¶
type SourceFile interface {
// Values returns every value of a key within a section, in file order.
Values(section, key string) []string
// Render writes the file back out.
Render() string
}
SourceFile is the parsed-file behaviour the IR needs, kept as an interface so package ir does not depend on the parser and generated units can omit it.
type Unit ¶
type Unit struct {
// Path is the file this unit came from, or a synthetic name when the
// unit was generated by conversion rather than read from disk.
Path string
// Name is the file's base name without its extension: `web.container`
// has the name `web`.
Name string
Kind UnitKind
// Image is the `Image=` value for a container unit.
Image string
// Mounts are the decomposed `Volume=` entries.
Mounts []Mount
// Ports are the decomposed `PublishPort=` entries.
Ports []Port
// Networks are the raw `Network=` values.
Networks []string
// Environment holds `Environment=` entries in declaration order.
Environment []EnvVar
// User and Group are the `User=` and `Group=` values.
User string
Group string
// GroupAdd holds the `GroupAdd=` values.
GroupAdd []string
// UserNS is the `UserNS=` value.
UserNS string
// AutoUpdate is the `AutoUpdate=` value.
AutoUpdate string
// Pod is the `Pod=` value, naming the pod unit this container joins.
Pod string
// Notify is the `Notify=` value.
Notify string
// Restart is `Restart=` from the `[Service]` section.
Restart string
// HasInstall records whether an `[Install]` section is present at all,
// even empty. QD022 turns on that distinction.
HasInstall bool
// InstallKeys are the keys found in `[Install]`.
InstallKeys []KeyValue
// HasHealthCmd records whether a healthcheck is configured, which
// `Notify=healthy` requires.
HasHealthCmd bool
// Source is the parsed file, retained so fixes can rewrite it and rules
// can reach keys the IR does not model. Nil for generated units.
Source SourceFile
// Entries is every assignment in the file, with its section and line, so
// rules can examine keys the IR does not model. QD042 needs this to spot
// a key that is not modelled *because* it is not a real key.
Entries []SourceEntry
// contains filtered or unexported fields
}
Unit is one Quadlet unit file in normalised form.
func FromParsed ¶
FromParsed normalises an already-parsed unit file.
func (*Unit) KeyLine ¶
KeyLine returns the line a scalar key was declared on, or 0 if the unit did not set it. Findings are more useful pointing at a line than at a whole file.
func (*Unit) SetKeyLine ¶
SetKeyLine records where a key was declared. Used by loaders.
type UnitKind ¶
type UnitKind string
UnitKind is the type of a Quadlet unit, determined by its file extension.
func KindFromPath ¶
KindFromPath derives the unit kind from a file name's extension.