diff --git a/pkg/metadata/Dockerfile b/pkg/metadata/Dockerfile index 9285cad9d..13ec973b4 100644 --- a/pkg/metadata/Dockerfile +++ b/pkg/metadata/Dockerfile @@ -6,10 +6,13 @@ ENV GOPATH=/go PATH=$PATH:/go/bin COPY . /go/src/metadata/ RUN go-compile.sh /go/src/metadata +RUN mkdir -p out/tmp out/var out/dev out/etc + FROM scratch ENTRYPOINT [] CMD [] WORKDIR / COPY --from=mirror /go/bin/metadata /usr/bin/metadata +COPY --from=mirror /out/ / CMD ["/usr/bin/metadata"] -LABEL org.mobyproject.config='{"binds": ["/dev:/dev", "/var:/var", "/etc/resolv.conf:/etc/resolv.conf"], "capabilities": ["CAP_SYS_ADMIN"]}' +LABEL org.mobyproject.config='{"binds": ["/dev:/dev", "/var:/var", "/etc/resolv.conf:/etc/resolv.conf"], "tmpfs": ["/tmp"], "readonly": true, "capabilities": ["CAP_SYS_ADMIN"]}' diff --git a/pkg/metadata/main.go b/pkg/metadata/main.go index b151137f0..09963e517 100644 --- a/pkg/metadata/main.go +++ b/pkg/metadata/main.go @@ -14,17 +14,11 @@ const ( // ConfigPath is where the data is extracted to ConfigPath = "/var/config" - // MountPoint is where the CDROM is mounted - MountPoint = "/cdrom" - // Hostname is the filename in configPath where the hostname is stored Hostname = "hostname" // SSH is the path where sshd configuration from the provider is stored SSH = "ssh" - - // TODO(rneugeba): Need to check this is the same everywhere - cdromDev = "/dev/sr0" ) // Provider is a generic interface for metadata/userdata providers. @@ -48,7 +42,7 @@ var cdromProviders []Provider func init() { netProviders = []Provider{NewGCP(), NewVultr(), NewAWS()} - cdromProviders = []Provider{NewCDROM()} + cdromProviders = ListCDROMs() } func main() { @@ -69,19 +63,8 @@ func main() { } } if !found { - log.Printf("Trying CDROM") - if err := os.MkdirAll(MountPoint, 0755); err != nil { - log.Printf("CDROM: Failed to create %s: %s", MountPoint, err) - goto ErrorOut - } - if err := mountCDROM(cdromDev, MountPoint); err != nil { - log.Printf("Failed to mount cdrom: %s", err) - goto ErrorOut - } - defer syscall.Unmount(MountPoint, 0) - // Don't worry about removing MountPoint. We are in a container - for _, p = range cdromProviders { + log.Printf("Trying %s", p.String()) if p.Probe() { log.Printf("%s: Probe succeeded", p) userdata, err = p.Extract() @@ -91,7 +74,6 @@ func main() { } } -ErrorOut: if !found { log.Printf("No metadata/userdata found. Bye") return @@ -202,9 +184,3 @@ func processUserData(data []byte) error { return nil } - -// mountCDROM mounts a CDROM/DVD device under mountPoint -func mountCDROM(device, mountPoint string) error { - // We may need to poll a little for device ready - return syscall.Mount(device, mountPoint, "iso9660", syscall.MS_RDONLY, "") -} diff --git a/pkg/metadata/provider_cdrom.go b/pkg/metadata/provider_cdrom.go index e28951f24..b181b3dcf 100644 --- a/pkg/metadata/provider_cdrom.go +++ b/pkg/metadata/provider_cdrom.go @@ -3,39 +3,73 @@ package main import ( "fmt" "io/ioutil" - "os" "path" + "path/filepath" + "syscall" ) const ( configFile = "config" + cdromDevs = "/dev/sr[0-9]*" ) // ProviderCDROM is the type implementing the Provider interface for CDROMs // It looks for a file called 'configFile' in the root type ProviderCDROM struct { + device string + mountPoint string + err error + data []byte +} + +// ListCDROMs lists all the cdroms in the system +func ListCDROMs() []Provider { + cdroms, err := filepath.Glob(cdromDevs) + if err != nil { + // Glob can only error on invalid pattern + panic(fmt.Sprintf("Invalid glob pattern: %s", cdromDevs)) + } + providers := []Provider{} + for _, device := range cdroms { + providers = append(providers, NewCDROM(device)) + } + return providers } // NewCDROM returns a new ProviderCDROM -func NewCDROM() *ProviderCDROM { - return &ProviderCDROM{} +func NewCDROM(device string) *ProviderCDROM { + mountPoint, err := ioutil.TempDir("", "cd") + p := ProviderCDROM{device, mountPoint, err, []byte{}} + if err == nil { + if p.err = p.mount(); p.err == nil { + p.data, p.err = ioutil.ReadFile(path.Join(p.mountPoint, configFile)) + p.unmount() + } + } + return &p } func (p *ProviderCDROM) String() string { - return "CDROM" + return "CDROM " + p.device } // Probe checks if the CD has the right file func (p *ProviderCDROM) Probe() bool { - _, err := os.Stat(path.Join(MountPoint, configFile)) - return (!os.IsNotExist(err)) + return len(p.data) != 0 } // Extract gets both the CDROM specific and generic userdata func (p *ProviderCDROM) Extract() ([]byte, error) { - data, err := ioutil.ReadFile(path.Join(MountPoint, configFile)) - if err != nil { - return nil, fmt.Errorf("CDROM: Error reading file: %s", err) - } - return data, nil + return p.data, p.err +} + +// mount mounts a CDROM/DVD device under mountPoint +func (p *ProviderCDROM) mount() error { + // We may need to poll a little for device ready + return syscall.Mount(p.device, p.mountPoint, "iso9660", syscall.MS_RDONLY, "") +} + +// unmount removes the mount +func (p *ProviderCDROM) unmount() { + _ = syscall.Unmount(p.mountPoint, 0) }