Hello community, here is the log from the commit of package ignition for openSUSE:Factory checked in at 2019-10-02 14:55:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ignition (Old) and /work/SRC/openSUSE:Factory/.ignition.new.2352 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "ignition" Wed Oct 2 14:55:55 2019 rev:5 rq:734560 version:2.0.1+git20190925.641ec6a Changes: -------- --- /work/SRC/openSUSE:Factory/ignition/ignition.changes 2019-09-11 10:36:08.007283333 +0200 +++ /work/SRC/openSUSE:Factory/.ignition.new.2352/ignition.changes 2019-10-02 14:55:58.975272654 +0200 @@ -1,0 +2,24 @@ +Fri Sep 27 11:17:00 UTC 2019 - kukuk@suse.de + +- Update to version 2.0.1+git20190925.641ec6a: + * selinux: use /run/systemd/relabel-extra.d for etc + * resource/url: Don't use a tmpfile in FetchToBuffer + * resource/url: use only needed ifaces in fetchFrom* + * resource/url: make FetchFrom* private + * Add a `fetch` stage + * build: Add `make install` + * tests: fix bb tests for size/start 0 + * Continue on empty GPT partition label + * files/selinux: deglob user/group related paths + * stages/files: relabel masking symlinks for systemd + * engine: Write `/run/ignition.json` atomically + * vendor: Add github.com/google/renameio + * stages/filesystems: drop stray debug print + * doc/supported-platforms: mention qemu version requirements + * Source build file correctly + * resource/url: update schema version in Accept header + * fix check path mount +- Drop 0001-Continue-on-empty-GPT-partition-label.patch: Added + upstream + +------------------------------------------------------------------- Old: ---- 0001-Continue-on-empty-GPT-partition-label.patch ignition-2.0.1+git20190802.d523754.tar.xz New: ---- ignition-2.0.1+git20190925.641ec6a.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ignition.spec ++++++ --- /var/tmp/diff_new_pack.oT9W41/_old 2019-10-02 14:55:59.987269999 +0200 +++ /var/tmp/diff_new_pack.oT9W41/_new 2019-10-02 14:55:59.991269989 +0200 @@ -17,14 +17,13 @@ Name: ignition -Version: 2.0.1+git20190802.d523754 +Version: 2.0.1+git20190925.641ec6a Release: 0 Summary: First boot installer and configuration tool License: Apache-2.0 Group: System/Management URL: https://github.com/coreos/ignition Source: %{name}-%{version}.tar.xz -Patch1: 0001-Continue-on-empty-GPT-partition-label.patch Requires: dracut BuildRequires: dracut BuildRequires: libblkid-devel @@ -41,7 +40,6 @@ %prep %setup -q -%patch1 -p1 %build sed -i -e 's|go build -ldflags|go build -buildmode=pie -ldflags|g' build ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.oT9W41/_old 2019-10-02 14:56:00.039269863 +0200 +++ /var/tmp/diff_new_pack.oT9W41/_new 2019-10-02 14:56:00.039269863 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">git://github.com/coreos/ignition.git</param> - <param name="changesrevision">dedd8ddd5da76a78e630533d87d43b2a4a323e22</param> + <param name="changesrevision">641ec6a44062f956bf1d46cf10824032a1996590</param> </service> </servicedata> \ No newline at end of file ++++++ ignition-2.0.1+git20190802.d523754.tar.xz -> ignition-2.0.1+git20190925.641ec6a.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/Makefile new/ignition-2.0.1+git20190925.641ec6a/Makefile --- old/ignition-2.0.1+git20190802.d523754/Makefile 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/Makefile 2019-09-25 21:37:39.000000000 +0200 @@ -1,9 +1,25 @@ export GO111MODULE=on +# Canonical version of this in https://github.com/coreos/coreos-assembler/blob/6eb97016f4dab7d13aa00ae10846... +GOARCH:=$(shell uname -m) +ifeq ($(GOARCH),x86_64) + GOARCH=amd64 +else ifeq ($(GOARCH),aarch64) + GOARCH=arm64 +endif + .PHONY: all all: ./build +# This currently assumes you're using https://github.com/coreos/ignition-dracut/ +# If in the future any other initramfs integration appears, feel free to add a PR +# to make this configurable. +.PHONY: install +install: all + install -m 0755 -D -t $(DESTDIR)/usr/lib/dracut/modules.d/30ignition bin/$(GOARCH)/ignition + install -m 0755 -D -t $(DESTDIR)/usr/bin bin/$(GOARCH)/ignition-validate + .PHONY: vendor vendor: @go mod vendor diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/build_blackbox_tests new/ignition-2.0.1+git20190925.641ec6a/build_blackbox_tests --- old/ignition-2.0.1+git20190802.d523754/build_blackbox_tests 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/build_blackbox_tests 2019-09-25 21:37:39.000000000 +0200 @@ -10,7 +10,7 @@ GLDFLAGS+="-X github.com/coreos/ignition/v2/internal/distro.usermodCmd=usermod-stub " GLDFLAGS+="-X github.com/coreos/ignition/v2/internal/distro.blackboxTesting=true " -. build +. ./build PKG=$(go list ./tests/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/doc/supported-platforms.md new/ignition-2.0.1+git20190925.641ec6a/doc/supported-platforms.md --- old/ignition-2.0.1+git20190802.d523754/doc/supported-platforms.md 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/doc/supported-platforms.md 2019-09-25 21:37:39.000000000 +0200 @@ -8,7 +8,7 @@ * [VMware] - Use the VMware Guestinfo variables `ignition.config.data` and `ignition.config.data.encoding` to provide the config and its encoding to the virtual machine. Valid encodings are "", "base64", and "gzip+base64". Guestinfo variables can be provided directly or via an OVF environment, with priority given to variables specified directly. * [Google Compute Platform] - Ignition will read its configuration from the instance metadata entry named "user-data". SSH keys are handled by coreos-metadata. * [Packet] - Ignition will read its configuration from the instance userdata. SSH keys are handled by coreos-metadata. -* [QEMU] - Ignition will read its configuration from the 'opt/com.coreos/config' key on the QEMU Firmware Configuration Device. +* [QEMU] - Ignition will read its configuration from the 'opt/com.coreos/config' key on the QEMU Firmware Configuration Device (available in QEMU 2.4.0 and higher). * [DigitalOcean] - Ignition will read its configuration from the droplet userdata. SSH keys and network configuration are handled by coreos-metadata. Ignition is under active development so expect this list to expand in the coming months. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/go.mod new/ignition-2.0.1+git20190925.641ec6a/go.mod --- old/ignition-2.0.1+git20190802.d523754/go.mod 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/go.mod 2019-09-25 21:37:39.000000000 +0200 @@ -8,6 +8,7 @@ github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 github.com/coreos/vcontext v0.0.0-20190529201340-22b159166068 github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384 // indirect + github.com/google/renameio v0.1.0 github.com/google/uuid v1.1.1 github.com/kr/pretty v0.1.0 // indirect github.com/pin/tftp v2.1.0+incompatible diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/go.sum new/ignition-2.0.1+git20190925.641ec6a/go.sum --- old/ignition-2.0.1+git20190802.d523754/go.sum 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/go.sum 2019-09-25 21:37:39.000000000 +0200 @@ -12,6 +12,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384 h1:xNwo3yd3PZYRDAr/Dz0sBfDWY6El2xPCKJrwJVfMFjY= github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/engine.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/engine.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/engine.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/engine.go 2019-09-25 21:37:39.000000000 +0200 @@ -39,6 +39,7 @@ "github.com/coreos/vcontext/report" "github.com/coreos/vcontext/validate" + "github.com/google/renameio" ) const ( @@ -166,7 +167,7 @@ e.Logger.Crit("failed to marshal cached config: %v", err) return } - if err = ioutil.WriteFile(e.ConfigCache, b, 0640); err != nil { + if err = renameio.WriteFile(e.ConfigCache, b, 0640); err != nil { e.Logger.Crit("failed to write cached config: %v", err) return } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/disks/filesystems.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/disks/filesystems.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/disks/filesystems.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/disks/filesystems.go 2019-09-25 21:37:39.000000000 +0200 @@ -37,7 +37,6 @@ // createFilesystems creates the filesystems described in config.Storage.Filesystems. func (s stage) createFilesystems(config types.Config) error { fss := config.Storage.Filesystems - s.Logger.Info("fss: %v", fss) if len(fss) == 0 { return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/fetch/fetch.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/fetch/fetch.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/fetch/fetch.go 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/fetch/fetch.go 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,64 @@ +// Copyright 2019 Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The storage stage is responsible for partitioning disks, creating RAID +// arrays, formatting partitions, writing files, writing systemd units, and +// writing network units. + +package disks + +import ( + "github.com/coreos/ignition/v2/config/v3_1_experimental/types" + "github.com/coreos/ignition/v2/internal/exec/stages" + "github.com/coreos/ignition/v2/internal/exec/util" + "github.com/coreos/ignition/v2/internal/log" + "github.com/coreos/ignition/v2/internal/resource" +) + +const ( + name = "fetch" +) + +func init() { + stages.Register(creator{}) +} + +type creator struct{} + +func (creator) Create(logger *log.Logger, root string, _ resource.Fetcher) stages.Stage { + return &stage{ + Util: util.Util{ + DestDir: root, + Logger: logger, + }, + } +} + +func (creator) Name() string { + return name +} + +type stage struct { + util.Util +} + +func (stage) Name() string { + return name +} + +func (s stage) Run(_ types.Config) error { + // Nothing - all we do is fetch and allow anything else in the initramfs to run + s.Logger.Info("fetch complete") + return nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/files/files.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/files/files.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/files/files.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/files/files.go 2019-09-25 21:37:39.000000000 +0200 @@ -17,7 +17,9 @@ import ( "errors" "fmt" + "io/ioutil" "os" + "path/filepath" "strings" "github.com/coreos/ignition/v2/config/v3_1_experimental/types" @@ -30,6 +32,9 @@ const ( name = "files" + + // see https://github.com/systemd/systemd/commit/65e183d7899eb3725d3009196ac4decf10... + relabelExtraDir = "/run/systemd/relabel-extra.d" ) var ( @@ -83,10 +88,18 @@ } // add systemd unit to relabel files - if err := s.addRelabelUnit(config); err != nil { + if err := s.addRelabelUnit(); err != nil { return fmt.Errorf("failed to add relabel unit: %v", err) } + // Add a file in /run/systemd/relabel-extra.d/ with paths that need to be relabeled + // as early as possible (e.g. systemd units so systemd can read them while building its + // graph). These are relabeled very early (right after policy load) so it cannot relabel + // across mounts. Only relabel things in /etc here. + if err := s.addRelabelExtraFile(); err != nil { + return fmt.Errorf("failed to write systemd relabel file: %v", err) + } + return nil } @@ -130,8 +143,8 @@ // addRelabelUnit creates and enables a runtime systemd unit to run restorecon // if there are files that need to be relabeled. -func (s *stage) addRelabelUnit(config types.Config) error { - if s.toRelabel == nil || len(s.toRelabel) == 0 { +func (s *stage) addRelabelUnit() error { + if len(s.toRelabel) == 0 { return nil } contents := `[Unit] @@ -179,3 +192,27 @@ _, err = f.WriteString(strings.Join(s.toRelabel, "\000") + "\000") return err } + +// addRelabelExtraFile writes a file to /run/systemd/relabel-extra.d/ with a list of files +// that should be relabeled immediately after policy load. In our case that's everything we +// wrote under /etc. This ensures systemd can access the files when building it's graph. +func (s stage) addRelabelExtraFile() error { + relabelFilePath := filepath.Join(relabelExtraDir, "ignition.relabel") + s.Logger.Info("adding relabel-extra.d/ file: %q", relabelFilePath) + defer s.Logger.Info("finished adding relabel file") + + relabelFileContents := "" + for _, file := range s.toRelabel { + if strings.HasPrefix(file, "/etc") { + relabelFileContents += file + "\n" + } + } + if relabelFileContents == "" { + return nil + } + if err := os.MkdirAll(relabelExtraDir, 0755); err != nil { + return err + } + + return ioutil.WriteFile(relabelFilePath, []byte(relabelFileContents), 0644) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/files/passwd.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/files/passwd.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/files/passwd.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/files/passwd.go 2019-09-25 21:37:39.000000000 +0200 @@ -16,10 +16,29 @@ import ( "fmt" + "path/filepath" "github.com/coreos/ignition/v2/config/v3_1_experimental/types" ) +func (s *stage) expandGlobList(globs ...string) ([]string, error) { + ret := []string{} + for _, glob := range globs { + matches, err := filepath.Glob(filepath.Join(s.DestDir, glob)) + if err != nil { + return nil, err + } + for _, match := range matches { + rel, err := filepath.Rel(s.DestDir, match) + if err != nil { + return nil, err + } + ret = append(ret, filepath.Join("/", rel)) + } + } + return ret, nil +} + // createPasswd creates the users and groups as described in config.Passwd. func (s *stage) createPasswd(config types.Config) error { if err := s.createGroups(config); err != nil { @@ -33,13 +52,21 @@ // to be safe, just blanket mark all passwd-related files rather than // trying to make it more granular based on which executables we ran if len(config.Passwd.Groups) != 0 || len(config.Passwd.Users) != 0 { - s.relabel( - "/etc/passwd*", + // Expand the globs now so tools that do not do glob expansion can parse them. + // Do this before handling files/links/dirs so we don't accidently expand paths + // for those if the user specifies a path which includes globbing characters. + deglobbed, err := s.expandGlobList("/etc/passwd*", "/etc/group*", "/etc/shadow*", "/etc/gshadow*", "/etc/subuid*", - "/etc/subgid*", + "/etc/subgid*") + if err != nil { + return err + } + + s.relabel(deglobbed...) + s.relabel( "/etc/.pwd.lock", "/home", "/root", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/files/units.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/files/units.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/files/units.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/files/units.go 2019-09-25 21:37:39.000000000 +0200 @@ -50,12 +50,18 @@ enabledOneUnit = true } if unit.Mask != nil && *unit.Mask { + relabelpath := "" if err := s.Logger.LogOp( - func() error { return s.MaskUnit(unit) }, + func() error { + var err error + relabelpath, err = s.MaskUnit(unit) + return err + }, "masking unit %q", unit.Name, ); err != nil { return err } + s.relabel(relabelpath) } } // and relabel the preset file itself if we enabled/disabled something diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/mount/mount.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/mount/mount.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/stages/mount/mount.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/stages/mount/mount.go 2019-09-25 21:37:39.000000000 +0200 @@ -66,7 +66,7 @@ func (s stage) Run(config types.Config) error { fss := []types.Filesystem{} for _, fs := range config.Storage.Filesystems { - if fs.Path != nil || *fs.Path != "" { + if fs.Path != nil && *fs.Path != "" { fss = append(fss, fs) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/util/blkid.c new/ignition-2.0.1+git20190925.641ec6a/internal/exec/util/blkid.c --- old/ignition-2.0.1+git20190802.d523754/internal/exec/util/blkid.c 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/util/blkid.c 2019-09-25 21:37:39.000000000 +0200 @@ -200,6 +200,10 @@ // label ctmp = blkid_partition_get_name(part); + // If the GPT label is empty, then libblkid will return NULL instead of an empty string. + // There is no NULL value in GPT, so just reset to empty. + if (!ctmp) + ctmp = ""; err = checked_copy(info->label, ctmp, PART_INFO_BUF_SIZE); if (err) return err; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/exec/util/unit.go new/ignition-2.0.1+git20190925.641ec6a/internal/exec/util/unit.go --- old/ignition-2.0.1+git20190802.d523754/internal/exec/util/unit.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/exec/util/unit.go 2019-09-25 21:37:39.000000000 +0200 @@ -18,6 +18,7 @@ "fmt" "net/url" "os" + "path/filepath" "github.com/coreos/ignition/v2/config/v3_1_experimental/types" "github.com/coreos/ignition/v2/internal/distro" @@ -88,19 +89,25 @@ }, nil } -func (ut Util) MaskUnit(unit types.Unit) error { +// MaskUnit writes a symlink to /dev/null to mask the specified unit and returns the path of that unit +// without the sysroot prefix +func (ut Util) MaskUnit(unit types.Unit) (string, error) { path, err := ut.JoinPath(SystemdUnitsPath(), unit.Name) if err != nil { - return err + return "", err } if err := MkdirForFile(path); err != nil { - return err + return "", err } if err := os.RemoveAll(path); err != nil { - return err + return "", err } - return os.Symlink("/dev/null", path) + if err := os.Symlink("/dev/null", path); err != nil { + return "", err + } + // not the same as the path above, since this lacks the sysroot prefix + return filepath.Join("/", SystemdUnitsPath(), unit.Name), nil } func (ut Util) EnableUnit(unit types.Unit) error { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/main.go new/ignition-2.0.1+git20190925.641ec6a/internal/main.go --- old/ignition-2.0.1+git20190802.d523754/internal/main.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/main.go 2019-09-25 21:37:39.000000000 +0200 @@ -23,6 +23,7 @@ "github.com/coreos/ignition/v2/internal/exec" "github.com/coreos/ignition/v2/internal/exec/stages" _ "github.com/coreos/ignition/v2/internal/exec/stages/disks" + _ "github.com/coreos/ignition/v2/internal/exec/stages/fetch" _ "github.com/coreos/ignition/v2/internal/exec/stages/files" _ "github.com/coreos/ignition/v2/internal/exec/stages/mount" _ "github.com/coreos/ignition/v2/internal/exec/stages/umount" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/internal/resource/url.go new/ignition-2.0.1+git20190925.641ec6a/internal/resource/url.go --- old/ignition-2.0.1+git20190802.d523754/internal/resource/url.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/internal/resource/url.go 2019-09-25 21:37:39.000000000 +0200 @@ -54,7 +54,7 @@ // config is being fetched ConfigHeaders = http.Header{ "Accept-Encoding": []string{"identity"}, - "Accept": []string{"application/vnd.coreos.ignition+json; version=2.2.0, application/vnd.coreos.ignition+json; version=1; q=0.5, */*; q=0.1"}, + "Accept": []string{"application/vnd.coreos.ignition+json;version=3.0.0, */*;q=0.1"}, } ) @@ -100,25 +100,50 @@ // in the contents of the file and delete it. It will return the downloaded // contents, or an error if one was encountered. func (f *Fetcher) FetchToBuffer(u url.URL, opts FetchOptions) ([]byte, error) { - file, err := ioutil.TempFile("", "ignition") - if err != nil { - return nil, err - } - defer os.Remove(file.Name()) - defer file.Close() - err = f.Fetch(u, file, opts) - if err != nil { - return nil, err + var err error + dest := new(bytes.Buffer) + switch u.Scheme { + case "http", "https": + err = f.fetchFromHTTP(u, dest, opts) + case "tftp": + err = f.fetchFromTFTP(u, dest, opts) + case "data": + err = f.fetchFromDataURL(u, dest, opts) + case "s3": + buf := &s3buf{ + WriteAtBuffer: aws.NewWriteAtBuffer([]byte{}), + } + err = f.fetchFromS3(u, buf, opts) + return buf.Bytes(), err + case "": + return nil, nil + default: + return nil, ErrSchemeUnsupported } - _, err = file.Seek(0, os.SEEK_SET) - if err != nil { - return nil, err + return dest.Bytes(), err +} + +// s3buf is a wrapper around the aws.WriteAtBuffer that also allows reading and seeking. +// Read() and Seek() are only safe to call after the download call is made. This is only for +// use with fetchFromS3* functions. +type s3buf struct { + *aws.WriteAtBuffer + // only safe to call read/seek after finishing writing. Not safe for parallel use + reader io.ReadSeeker +} + +func (s *s3buf) Read(p []byte) (int, error) { + if s.reader == nil { + s.reader = bytes.NewReader(s.Bytes()) } - res, err := ioutil.ReadAll(file) - if err != nil { - return nil, err + return s.reader.Read(p) +} + +func (s *s3buf) Seek(offset int64, whence int) (int64, error) { + if s.reader == nil { + s.reader = bytes.NewReader(s.Bytes()) } - return res, nil + return s.reader.Seek(offset, whence) } // Fetch calls the appropriate FetchFrom* function based on the scheme of the @@ -134,13 +159,13 @@ func (f *Fetcher) Fetch(u url.URL, dest *os.File, opts FetchOptions) error { switch u.Scheme { case "http", "https": - return f.FetchFromHTTP(u, dest, opts) + return f.fetchFromHTTP(u, dest, opts) case "tftp": - return f.FetchFromTFTP(u, dest, opts) + return f.fetchFromTFTP(u, dest, opts) case "data": - return f.FetchFromDataURL(u, dest, opts) + return f.fetchFromDataURL(u, dest, opts) case "s3": - return f.FetchFromS3(u, dest, opts) + return f.fetchFromS3(u, dest, opts) case "": return nil default: @@ -150,7 +175,7 @@ // FetchFromTFTP fetches a resource from u via TFTP into dest, returning an // error if one is encountered. -func (f *Fetcher) FetchFromTFTP(u url.URL, dest *os.File, opts FetchOptions) error { +func (f *Fetcher) fetchFromTFTP(u url.URL, dest io.Writer, opts FetchOptions) error { if !strings.ContainsRune(u.Host, ':') { u.Host = u.Host + ":69" } @@ -212,7 +237,7 @@ // FetchFromHTTP fetches a resource from u via HTTP(S) into dest, returning an // error if one is encountered. -func (f *Fetcher) FetchFromHTTP(u url.URL, dest *os.File, opts FetchOptions) error { +func (f *Fetcher) fetchFromHTTP(u url.URL, dest io.Writer, opts FetchOptions) error { // for the case when "config is not valid" // this if necessary if not spawned through kola (e.g. Packet Dashboard) if f.client == nil { @@ -248,7 +273,7 @@ // FetchFromDataURL writes the data stored in the dataurl u into dest, returning // an error if one is encountered. -func (f *Fetcher) FetchFromDataURL(u url.URL, dest *os.File, opts FetchOptions) error { +func (f *Fetcher) fetchFromDataURL(u url.URL, dest io.Writer, opts FetchOptions) error { if opts.Compression != "" { return ErrCompressionUnsupported } @@ -260,11 +285,16 @@ return f.decompressCopyHashAndVerify(dest, bytes.NewBuffer(url.Data), opts) } +type s3target interface { + io.WriterAt + io.ReadSeeker +} + // FetchFromS3 gets data from an S3 bucket as described by u and writes it into // dest, returning an error if one is encountered. It will attempt to acquire // IAM credentials from the EC2 metadata service, and if this fails will attempt // to fetch the object with anonymous credentials. -func (f *Fetcher) FetchFromS3(u url.URL, dest *os.File, opts FetchOptions) error { +func (f *Fetcher) fetchFromS3(u url.URL, dest s3target, opts FetchOptions) error { if opts.Compression != "" { return ErrCompressionUnsupported } @@ -337,7 +367,7 @@ return nil } -func (f *Fetcher) fetchFromS3WithCreds(ctx context.Context, dest *os.File, input *s3.GetObjectInput, sess *session.Session) error { +func (f *Fetcher) fetchFromS3WithCreds(ctx context.Context, dest s3target, input *s3.GetObjectInput, sess *session.Session) error { httpClient, err := defaultHTTPClient() if err != nil { return err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/tests/negative/partitions/zeroes.go new/ignition-2.0.1+git20190925.641ec6a/tests/negative/partitions/zeroes.go --- old/ignition-2.0.1+git20190802.d523754/tests/negative/partitions/zeroes.go 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/tests/negative/partitions/zeroes.go 2019-09-25 21:37:39.000000000 +0200 @@ -29,8 +29,9 @@ name := "partition.match.failstofill" in := types.GetBaseDisk() in[0].Partitions = append(in[0].Partitions, &types.Partition{ - Number: 10, - Length: 65536, + Number: 10, + Length: 65536, + TypeCode: "blank", }) out := in config := `{ @@ -42,7 +43,7 @@ "partitions": [ { "number": 9, - "size": 0 + "sizeMiB": 0 } ] } @@ -66,8 +67,9 @@ //insert a gap before 9 tmp := in[0].Partitions[9-2-1] in[0].Partitions[9-2-1] = &types.Partition{ - Number: 10, - Length: 65536, + Number: 10, + Length: 65536, + TypeCode: "blank", } in[0].Partitions = append(in[0].Partitions, tmp) out := in @@ -80,7 +82,7 @@ "partitions": [ { "number": 9, - "start": 0 + "startMiB": 0 } ] } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/.travis.yml new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/.travis.yml --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/.travis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/.travis.yml 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,16 @@ +sudo: required +dist: trusty +language: go +go: + - "1.11" + +install: + - go get -t -v -d ./... + +script: + # Check whether files are syntactically correct. + - "gofmt -l $(find . -name '*.go' | tr '\\n' ' ') >/dev/null" + # Check whether files were not gofmt'ed. + - "gosrc=$(find . -name '*.go' | tr '\\n' ' '); [ $(gofmt -l $gosrc 2>&- | wc -l) -eq 0 ] || (echo 'gofmt was not run on these files:'; gofmt -l $gosrc 2>&-; false)" + - go tool vet . + - go test -c -race . && sudo ./renameio.test -test.v diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/CONTRIBUTING.md new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/CONTRIBUTING.md --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/CONTRIBUTING.md 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/CONTRIBUTING.md 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,28 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to https://cla.developers.google.com/ to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. + +## Community Guidelines + +This project follows [Google's Open Source Community +Guidelines](https://opensource.google.com/conduct/). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/LICENSE new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/LICENSE --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/LICENSE 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/LICENSE 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/README.md new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/README.md --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/README.md 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,51 @@ +[![Build Status](https://travis-ci.org/google/renameio.svg?branch=master)](https://travis-ci.org/google/renameio) +[![GoDoc](https://godoc.org/github.com/google/renameio?status.svg)](https://godoc.org/github.com/google/renameio) +[![Go Report Card](https://goreportcard.com/badge/github.com/google/renameio)](https://goreportcard.com/report/github.com/google/renameio) + +The `renameio` Go package provides a way to atomically create or replace a file or +symbolic link. + +## Atomicity vs durability + +`renameio` concerns itself *only* with atomicity, i.e. making sure applications +never see unexpected file content (a half-written file, or a 0-byte file). + +As a practical example, consider https://manpages.debian.org/: if there is a +power outage while the site is updating, we are okay with losing the manpages +which were being rendered at the time of the power outage. They will be added in +a later run of the software. We are not okay with having a manpage replaced by a +0-byte file under any circumstances, though. + +## Advantages of this package + +There are other packages for atomically replacing files, and sometimes ad-hoc +implementations can be found in programs. + +A naive approach to the problem is to create a temporary file followed by a call +to `os.Rename()`. However, there are a number of subtleties which make the +correct sequence of operations hard to identify: + +* The temporary file should be removed when an error occurs, but a remove must + not be attempted if the rename succeeded, as a new file might have been + created with the same name. This renders a throwaway `defer + os.Remove(t.Name())` insufficient; state must be kept. + +* The temporary file must be created on the same file system (same mount point) + for the rename to work, but the TMPDIR environment variable should still be + respected, e.g. to direct temporary files into a separate directory outside of + the webserver’s document root but on the same file system. + +* On POSIX operating systems, the + [`fsync`](https://manpages.debian.org/stretch/manpages-dev/fsync.2) system + call must be used to ensure that the `os.Rename()` call will not result in a + 0-length file. + +This package attempts to get all of these details right, provides an intuitive, +yet flexible API and caters to use-cases where high performance is required. + +## Disclaimer + +This is not an official Google product (experimental or otherwise), it +is just code that happens to be owned by Google. + +This project is not affiliated with the Go project. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/doc.go new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/doc.go --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/doc.go 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/doc.go 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,21 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package renameio provides a way to atomically create or replace a file or +// symbolic link. +// +// Caveat: this package requires the file system rename(2) implementation to be +// atomic. Notably, this is not the case when using NFS with multiple clients: +// https://stackoverflow.com/a/41396801 +package renameio diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/go.mod new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/go.mod --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/go.mod 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/go.mod 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1 @@ +module github.com/google/renameio diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/tempfile.go new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/tempfile.go --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/tempfile.go 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/tempfile.go 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,175 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package renameio + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +// TempDir checks whether os.TempDir() can be used as a temporary directory for +// later atomically replacing files within dest. If no (os.TempDir() resides on +// a different mount point), dest is returned. +// +// Note that the returned value ceases to be valid once either os.TempDir() +// changes (e.g. on Linux, once the TMPDIR environment variable changes) or the +// file system is unmounted. +func TempDir(dest string) string { + return tempDir("", filepath.Join(dest, "renameio-TempDir")) +} + +func tempDir(dir, dest string) string { + if dir != "" { + return dir // caller-specified directory always wins + } + + // Chose the destination directory as temporary directory so that we + // definitely can rename the file, for which both temporary and destination + // file need to point to the same mount point. + fallback := filepath.Dir(dest) + + // The user might have overridden the os.TempDir() return value by setting + // the TMPDIR environment variable. + tmpdir := os.TempDir() + + testsrc, err := ioutil.TempFile(tmpdir, "."+filepath.Base(dest)) + if err != nil { + return fallback + } + cleanup := true + defer func() { + if cleanup { + os.Remove(testsrc.Name()) + } + }() + testsrc.Close() + + testdest, err := ioutil.TempFile(filepath.Dir(dest), "."+filepath.Base(dest)) + if err != nil { + return fallback + } + defer os.Remove(testdest.Name()) + testdest.Close() + + if err := os.Rename(testsrc.Name(), testdest.Name()); err != nil { + return fallback + } + cleanup = false // testsrc no longer exists + return tmpdir +} + +// PendingFile is a pending temporary file, waiting to replace the destination +// path in a call to CloseAtomicallyReplace. +type PendingFile struct { + *os.File + + path string + done bool + closed bool +} + +// Cleanup is a no-op if CloseAtomicallyReplace succeeded, and otherwise closes +// and removes the temporary file. +func (t *PendingFile) Cleanup() error { + if t.done { + return nil + } + // An error occurred. Close and remove the tempfile. Errors are returned for + // reporting, there is nothing the caller can recover here. + var closeErr error + if !t.closed { + closeErr = t.Close() + } + if err := os.Remove(t.Name()); err != nil { + return err + } + return closeErr +} + +// CloseAtomicallyReplace closes the temporary file and atomically replaces +// the destination file with it, i.e., a concurrent open(2) call will either +// open the file previously located at the destination path (if any), or the +// just written file, but the file will always be present. +func (t *PendingFile) CloseAtomicallyReplace() error { + // Even on an ordered file system (e.g. ext4 with data=ordered) or file + // systems with write barriers, we cannot skip the fsync(2) call as per + // Theodore Ts'o (ext2/3/4 lead developer): + // + // > data=ordered only guarantees the avoidance of stale data (e.g., the previous + // > contents of a data block showing up after a crash, where the previous data + // > could be someone's love letters, medical records, etc.). Without the fsync(2) + // > a zero-length file is a valid and possible outcome after the rename. + if err := t.Sync(); err != nil { + return err + } + t.closed = true + if err := t.Close(); err != nil { + return err + } + if err := os.Rename(t.Name(), t.path); err != nil { + return err + } + t.done = true + return nil +} + +// TempFile wraps ioutil.TempFile for the use case of atomically creating or +// replacing the destination file at path. +// +// If dir is the empty string, TempDir(filepath.Base(path)) is used. If you are +// going to write a large number of files to the same file system, store the +// result of TempDir(filepath.Base(path)) and pass it instead of the empty +// string. +// +// The file's permissions will be 0600 by default. You can change these by +// explicitly calling Chmod on the returned PendingFile. +func TempFile(dir, path string) (*PendingFile, error) { + f, err := ioutil.TempFile(tempDir(dir, path), "."+filepath.Base(path)) + if err != nil { + return nil, err + } + + return &PendingFile{File: f, path: path}, nil +} + +// Symlink wraps os.Symlink, replacing an existing symlink with the same name +// atomically (os.Symlink fails when newname already exists, at least on Linux). +func Symlink(oldname, newname string) error { + // Fast path: if newname does not exist yet, we can skip the whole dance + // below. + if err := os.Symlink(oldname, newname); err == nil || !os.IsExist(err) { + return err + } + + // We need to use ioutil.TempDir, as we cannot overwrite a ioutil.TempFile, + // and removing+symlinking creates a TOCTOU race. + d, err := ioutil.TempDir(filepath.Dir(newname), "."+filepath.Base(newname)) + if err != nil { + return err + } + defer os.RemoveAll(d) + + symlink := filepath.Join(d, "tmp.symlink") + if err := os.Symlink(oldname, symlink); err != nil { + return err + } + + if err := os.Rename(symlink, newname); err != nil { + return err + } + + return os.RemoveAll(d) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/writefile.go new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/writefile.go --- old/ignition-2.0.1+git20190802.d523754/vendor/github.com/google/renameio/writefile.go 1970-01-01 01:00:00.000000000 +0100 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/github.com/google/renameio/writefile.go 2019-09-25 21:37:39.000000000 +0200 @@ -0,0 +1,38 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package renameio + +import "os" + +// WriteFile mirrors ioutil.WriteFile, replacing an existing file with the same +// name atomically. +func WriteFile(filename string, data []byte, perm os.FileMode) error { + t, err := TempFile("", filename) + if err != nil { + return err + } + defer t.Cleanup() + + // Set permissions before writing data, in case the data is sensitive. + if err := t.Chmod(perm); err != nil { + return err + } + + if _, err := t.Write(data); err != nil { + return err + } + + return t.CloseAtomicallyReplace() +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ignition-2.0.1+git20190802.d523754/vendor/modules.txt new/ignition-2.0.1+git20190925.641ec6a/vendor/modules.txt --- old/ignition-2.0.1+git20190802.d523754/vendor/modules.txt 2019-08-02 19:02:11.000000000 +0200 +++ new/ignition-2.0.1+git20190925.641ec6a/vendor/modules.txt 2019-09-25 21:37:39.000000000 +0200 @@ -52,6 +52,8 @@ github.com/davecgh/go-spew/spew # github.com/godbus/dbus v0.0.0-20181025153459-66d97aec3384 github.com/godbus/dbus +# github.com/google/renameio v0.1.0 +github.com/google/renameio # github.com/google/uuid v1.1.1 github.com/google/uuid # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af