Hello community,

here is the log from the commit of package docker for openSUSE:Factory checked 
in at 2017-03-22 23:18:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/docker (Old)
 and      /work/SRC/openSUSE:Factory/.docker.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "docker"

Wed Mar 22 23:18:14 2017 rev:52 rq:480841 version:1.13.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/docker/docker.changes    2017-02-03 
17:35:51.644330236 +0100
+++ /work/SRC/openSUSE:Factory/.docker.new/docker.changes       2017-03-22 
23:18:15.671939874 +0100
@@ -1,0 +2,53 @@
+Fri Mar 17 11:08:03 UTC 2017 - asa...@suse.com
+
+- Add a backport of fix to AppArmor lazy loading docker-exec case.
+  https://github.com/docker/docker/pull/31773
+  + pr31773-daemon-also-ensureDefaultApparmorProfile-in-exec-pat.patch
+
+-------------------------------------------------------------------
+Wed Mar  8 00:48:46 UTC 2017 - asa...@suse.com
+
+- Clean up docker-mount-secrets.patch to use the new swarm secrets internals of
+  Docker 1.13.0, which removes the need to implement any secret handling
+  ourselves. This resulted in a split up of the patch.
+  - docker-mount-secrets.patch
+  + secrets-0001-daemon-allow-directory-creation-in-run-secrets.patch
+  + secrets-0002-SUSE-implement-SUSE-container-secrets.patch
+
+-------------------------------------------------------------------
+Mon Mar  6 15:31:02 UTC 2017 - jmassaguer...@suse.com
+
+- Remove old plugins.json to prevent docker-1.13 to fail to start
+
+-------------------------------------------------------------------
+Mon Mar  6 12:52:14 UTC 2017 - jmassaguer...@suse.com
+
+- Fix bsc#1026827: systemd TasksMax default throttles docker
+
+-------------------------------------------------------------------
+Mon Mar  6 10:09:14 UTC 2017 - jmassaguer...@suse.com
+
+- Fix post section by adding shadow as a package requirement
+  Otherwise the groupadd instruction fails
+
+-------------------------------------------------------------------
+Sun Mar  5 04:54:52 UTC 2017 - asa...@suse.com
+
+- Add patch to fix TestDaemonCommand failure in %check. This is an upstream
+  bug, and has an upstream PR to fix it 
https://github.com/docker/docker/pull/31549.
+  + pr31549-cmd-docker-fix-TestDaemonCommand.patch
+
+-------------------------------------------------------------------
+Wed Feb  1 15:59:40 UTC 2017 - jmassaguer...@suse.com
+
+- update docker to 1.13.0
+
+  see details in https://github.com/docker/docker/releases/tag/v1.13.0
+
+- use the same buildflags for building docker and for building the
+  tests.
+
+- enable pkcs11:
+  
https://github.com/docker/docker/commit/37fa75b3447007bb8ea311f02610bb383b0db77f
+
+-------------------------------------------------------------------

Old:
----
  docker-1.12.6.tar.xz
  docker-mount-secrets.patch

New:
----
  docker-1.13.0.tar.xz
  pr31549-cmd-docker-fix-TestDaemonCommand.patch
  pr31773-daemon-also-ensureDefaultApparmorProfile-in-exec-pat.patch
  secrets-0001-daemon-allow-directory-creation-in-run-secrets.patch
  secrets-0002-SUSE-implement-SUSE-container-secrets.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ docker.spec ++++++
--- /var/tmp/diff_new_pack.x7rAzr/_old  2017-03-22 23:18:19.291427183 +0100
+++ /var/tmp/diff_new_pack.x7rAzr/_new  2017-03-22 23:18:19.295426616 +0100
@@ -36,7 +36,7 @@
 %global docker_migration_warnfile %{docker_store}/docker-update-message.txt
 %define docker_graph              %{docker_store}/graph
 %define git_version 78d1802
-%define version_unconverted 1.12.6
+%define version_unconverted 1.13.0
 %define __arch_install_post export NO_BRP_STRIP_DEBUG=true
 # When upgrading to a new version requires the service not to be restarted
 # Due to a long migration process update last_migration_version to the new 
version
@@ -44,7 +44,7 @@
 # 1.10.1
 %global last_migration_version 1.10.1
 Name:           docker
-Version:        1.12.6
+Version:        1.13.0
 Release:        0
 Summary:        The Linux container runtime
 License:        Apache-2.0
@@ -68,14 +68,21 @@
 # which is not snapshotted when images are committed. Note that if you modify
 # this patch, please also modify the patch in the suse-secrets-v<version>
 # branch in http://github.com/suse/docker.mirror.
-Patch200:       docker-mount-secrets.patch
+Patch200:       
secrets-0001-daemon-allow-directory-creation-in-run-secrets.patch
+Patch201:       secrets-0002-SUSE-implement-SUSE-container-secrets.patch
+# PATCH-FIX-UPSTREAM: Backports.
 Patch300:       integration-cli-fix-TestInfoEnsureSucceeds.patch
+Patch301:       pr31549-cmd-docker-fix-TestDaemonCommand.patch
+Patch302:       
pr31773-daemon-also-ensureDefaultApparmorProfile-in-exec-pat.patch
 BuildRequires:  audit
 BuildRequires:  bash-completion
+BuildRequires:  ca-certificates
 BuildRequires:  device-mapper-devel >= 1.2.68
 BuildRequires:  glibc-devel-static
 BuildRequires:  libapparmor-devel
 BuildRequires:  libbtrfs-devel >= 3.8
+BuildRequires:  libseccomp-devel
+BuildRequires:  libtool
 BuildRequires:  procps
 BuildRequires:  sqlite3-devel
 BuildRequires:  systemd-devel
@@ -83,12 +90,13 @@
 Requires:       apparmor-parser
 Requires:       bridge-utils
 Requires:       ca-certificates-mozilla
+Requires:       docker-libnetwork = 0.0.0+git20161019.0f53435
 # Containerd and runC are required as they are the only currently supported
 # execdrivers of Docker. NOTE: The version pinning here matches upstream's
 # Dockerfile to ensure that we don't use a slightly incompatible version of
 # runC or containerd (which would be bad).
-Requires:       containerd = 0.2.5+gitr569_2a5e70c
-Requires:       runc = 0.1.1+gitr2819_50a19c6
+Requires:       containerd = 0.2.5+gitr608_03e5862
+Requires:       runc = 0.1.1+gitr2942_2f7393a
 # Provides mkfs.ext4 - used by Docker when devicemapper storage driver is used
 Requires:       e2fsprogs
 Requires:       git-core >= 1.7
@@ -100,6 +108,7 @@
 Requires:       xz >= 4.9
 Requires(post): %fillup_prereq
 Requires(post): udev
+Requires(post): shadow
 # Not necessary, but must be installed to have a smooth upgrade.
 Recommends:     docker-image-migrator
 Conflicts:      lxc < 1.0
@@ -169,6 +178,7 @@
 # nothing
 %else
 %patch200 -p1
+%patch201 -p1
 %endif
 %ifnarch %{go_arches}
 %patch100 -p1
@@ -176,6 +186,8 @@
 %patch103 -p1
 %endif
 %patch300 -p1
+%patch301 -p1
+%patch302 -p1
 cp %{SOURCE7} .
 cp %{SOURCE10} .
 
@@ -188,9 +200,18 @@
 export PATH=$tmphack:$PATH
 %endif
 
+# Note that these commands do not allow %%elseif.
+# For versions equal to or below SLE12 && openSUSE_13.2 libdevmapper.h is not
+# recent enough to define dm_task_deferred_remove(). (This is not true of
+# SLE12_SP1 but we cannot distinguish it with this macro.)
+BUILDTAGS="exclude_graphdriver_aufs apparmor seccomp selinux pkcs11"
+%if 0%{?suse_version} <= 1320
+       BUILDTAGS="libdm_no_deferred_remove $BUILDTAGS"
+%endif
+
 (cat <<EOF
 export AUTO_GOPATH=1
-export DOCKER_BUILDTAGS="exclude_graphdriver_aufs apparmor selinux"
+export DOCKER_BUILDTAGS="$BUILDTAGS"
 export DOCKER_GITCOMMIT=%{git_version}
 EOF
 ) > docker_build_env
@@ -233,22 +254,13 @@
 
 cd $HOME/go/src/github.com/docker/docker
 
-# Note that these commands do not allow %%elseif.
-# For versions equal to or below SLE12 && openSUSE_13.2 libdevmapper.h is not
-# recent enough to define dm_task_deferred_remove(). (This is not true of
-# SLE12_SP1 but we cannot distinguish it with this macro.)
-EXCLUDE_TAGS=
-%if 0%{?suse_version} <= 1320
-       EXCLUDE_TAGS="libdm_no_deferred_remove $EXCLUDE_TAGS"
-%endif
-
 # The command is taken from hack/make/test-unit and various test runs.
 # Everything that follows github.com/docker/pkg/integration-cli are packages
 # containing tests that cannot run in an obs build context.
 PKG_LIST=$(go list -e \
                -f '{{if ne .Name "github.com/docker/docker"}} {{.ImportPath}}
                {{end}}'  \
-               -tags $EXCLUDE_TAGS \
+               -tags "$DOCKER_BUILDTAGS" \
                -a "${BUILDFLAGS[@]}" ... \
                | grep 'github.com/docker/docker' \
                | grep -v 'github.com/docker/docker/vendor' \
@@ -273,7 +285,7 @@
                | grep -v 'github.com/docker/docker/man$' \
                | grep -v 'github.com/docker/docker/pkg/integration$')
 
-go test -cover -ldflags -w -tags $EXCLUDE_TAGS -a -test.timeout=10m $PKG_LIST
+go test -cover -ldflags -w -tags "$DOCKER_BUILDTAGS" -a -test.timeout=10m 
$PKG_LIST
 %endif
 
 %install
@@ -282,11 +294,9 @@
 %ifarch %{go_arches}
 install -D -m755 bundles/latest/dynbinary-client/%{name} 
%{buildroot}/%{_bindir}/%{name}
 install -D -m755 bundles/latest/dynbinary-daemon/%{name}d 
%{buildroot}/%{_bindir}/%{name}d
-install -D -m755 bundles/latest/dynbinary-daemon/%{name}-proxy 
%{buildroot}/%{_bindir}/%{name}-proxy
 %else
 install -D -m755 bundles/latest/dyngccgo/%{name} 
%{buildroot}/%{_bindir}/%{name}
 install -D -m755 bundles/latest/dyngccgo/%{name}d 
%{buildroot}/%{_bindir}/%{name}d
-install -D -m755 bundles/latest/dyngccgo/%{name}-proxy 
%{buildroot}/%{_bindir}/%{name}-proxy
 %endif
 install -d %{buildroot}/%{_prefix}/lib/docker
 install -Dd -m 0755 \
@@ -374,6 +384,13 @@
         rm %{docker_migration_warnfile}
     fi
 fi
+# If plugins.json is present, docker will fail to start
+# https://github.com/docker/docker/releases/1.13.0
+if [ -e /var/lib/docker/plugins/plugins.json ];then
+  echo "Warning: Disabling previous installed plugins"
+  echo "Otherwise docker will fail to boot"
+  mv /var/lib/docker/plugins/plugins.json 
/var/lib/docker/plugins/_plugins.json.old
+fi
 %service_add_post %{name}.service
 %{fillup_only -n docker}
 
@@ -392,7 +409,6 @@
 %doc README.md LICENSE README_SUSE.md
 %{_bindir}/docker
 %{_bindir}/dockerd
-%{_bindir}/docker-proxy
 %{_sbindir}/rcdocker
 %{_libexecdir}/docker/
 %{_unitdir}/%{name}.service

++++++ _service ++++++
--- /var/tmp/diff_new_pack.x7rAzr/_old  2017-03-22 23:18:19.375415286 +0100
+++ /var/tmp/diff_new_pack.x7rAzr/_new  2017-03-22 23:18:19.379414720 +0100
@@ -3,8 +3,8 @@
     <param name="url">https://github.com/docker/docker.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="versionformat">1.12.6</param>
-    <param name="revision">v1.12.6</param>
+    <param name="versionformat">1.13.0</param>
+    <param name="revision">v1.13.0</param>
   </service>
   <service name="recompress" mode="disabled">
     <param name="file">docker-*.tar</param>

++++++ docker-1.12.6.tar.xz -> docker-1.13.0.tar.xz ++++++
/work/SRC/openSUSE:Factory/docker/docker-1.12.6.tar.xz 
/work/SRC/openSUSE:Factory/.docker.new/docker-1.13.0.tar.xz differ: char 25, 
line 1

++++++ docker.service ++++++
--- /var/tmp/diff_new_pack.x7rAzr/_old  2017-03-22 23:18:19.467402257 +0100
+++ /var/tmp/diff_new_pack.x7rAzr/_new  2017-03-22 23:18:19.471401690 +0100
@@ -23,7 +23,7 @@
 
 # Uncomment TasksMax if your systemd version supports it.
 # Only systemd 226 and above support this property.
-#TasksMax=infinity
+TasksMax=infinity
 
 # Set delegate yes so that systemd does not reset the cgroups of docker 
containers
 # Only systemd 218 and above support this property.

++++++ integration-cli-fix-TestInfoEnsureSucceeds.patch ++++++
--- /var/tmp/diff_new_pack.x7rAzr/_old  2017-03-22 23:18:19.491398857 +0100
+++ /var/tmp/diff_new_pack.x7rAzr/_new  2017-03-22 23:18:19.491398857 +0100
@@ -1,18 +1,8 @@
-From 0f0c0fcb5b956782385e25c7c6c625e6c79ac78f Mon Sep 17 00:00:00 2001
-From: Thomas Hipp <th...@suse.de>
-Date: Wed, 7 Sep 2016 10:54:09 +0200
-Subject: [PATCH] integration-cli: fix TestInfoEnsureSucceeds
-
-Signed-off-by: Thomas Hipp <th...@suse.de>
----
- integration-cli/docker_cli_info_test.go | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
 diff --git a/integration-cli/docker_cli_info_test.go 
b/integration-cli/docker_cli_info_test.go
-index a48e69a..c265a36 100644
+index 62ce7e2..46516f9 100644
 --- a/integration-cli/docker_cli_info_test.go
 +++ b/integration-cli/docker_cli_info_test.go
-@@ -36,7 +36,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
+@@ -40,7 +40,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
        }
  
        if DaemonIsLinux.Condition() {
@@ -20,7 +10,4 @@
 +              stringsToCheck = append(stringsToCheck, "Runtimes:", "Default 
Runtime: oci")
        }
  
-       if utils.ExperimentalBuild() {
--- 
-2.9.3
-
+       if experimentalDaemon {

++++++ pr31549-cmd-docker-fix-TestDaemonCommand.patch ++++++
>From dd7159060f60ea04007c069df189a29fda2c655f Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asa...@suse.de>
Date: Sun, 5 Mar 2017 15:25:11 +1100
Subject: [PATCH] cmd: docker: fix TestDaemonCommand

In more recent versions of Cobra, `--help` parsing is done before
anything else resulting in TestDaemonCommand not actually passing. I'm
actually unsure if this test ever passed since it appears that !daemon
is not being run as part of the test suite.

Signed-off-by: Aleksa Sarai <asa...@suse.de>
---
 cmd/docker/daemon_none.go      | 6 ++++--
 cmd/docker/daemon_none_test.go | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/cmd/docker/daemon_none.go b/cmd/docker/daemon_none.go
index 65f9f37be22f..6fbd00012526 100644
--- a/cmd/docker/daemon_none.go
+++ b/cmd/docker/daemon_none.go
@@ -12,8 +12,10 @@ import (
 
 func newDaemonCommand() *cobra.Command {
        return &cobra.Command{
-               Use:    "daemon",
-               Hidden: true,
+               Use:                "daemon",
+               Hidden:             true,
+               Args:               cobra.ArbitraryArgs,
+               DisableFlagParsing: true,
                RunE: func(cmd *cobra.Command, args []string) error {
                        return runDaemon()
                },
diff --git a/cmd/docker/daemon_none_test.go b/cmd/docker/daemon_none_test.go
index 32032fe1b344..bd42add98696 100644
--- a/cmd/docker/daemon_none_test.go
+++ b/cmd/docker/daemon_none_test.go
@@ -10,7 +10,7 @@ import (
 
 func TestDaemonCommand(t *testing.T) {
        cmd := newDaemonCommand()
-       cmd.SetArgs([]string{"--help"})
+       cmd.SetArgs([]string{"--version"})
        err := cmd.Execute()
 
        assert.Error(t, err, "Please run `dockerd`")
-- 
2.12.0

++++++ pr31773-daemon-also-ensureDefaultApparmorProfile-in-exec-pat.patch ++++++
>From 790a81ea9acce318d0e037771c253951b874140b Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asa...@suse.de>
Date: Mon, 13 Mar 2017 14:57:35 +1100
Subject: [PATCH] daemon: also ensureDefaultApparmorProfile in exec path

When 567ef8e7858c ("daemon: switch to 'ensure' workflow for AppArmor
profiles") was merged, it didn't correctly handle the exec path if
AppArmor profiles were deleted. Fix this by duplicating the
ensureDefaultApparmorProfile code in the exec code.

Fixes: 567ef8e7858c ("daemon: switch to 'ensure' workflow for AppArmor 
profiles")
Signed-off-by: Aleksa Sarai <asa...@suse.de>
---
 daemon/exec_linux.go | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/daemon/exec_linux.go b/daemon/exec_linux.go
index 5aeedc347027..bb11c11e447c 100644
--- a/daemon/exec_linux.go
+++ b/daemon/exec_linux.go
@@ -5,6 +5,7 @@ import (
        "github.com/docker/docker/daemon/caps"
        "github.com/docker/docker/daemon/exec"
        "github.com/docker/docker/libcontainerd"
+       "github.com/opencontainers/runc/libcontainer/apparmor"
        "github.com/opencontainers/runtime-spec/specs-go"
 )
 
@@ -23,5 +24,27 @@ func execSetPlatformOpt(c *container.Container, ec 
*exec.Config, p *libcontainer
        if ec.Privileged {
                p.Capabilities = caps.GetAllCapabilities()
        }
+       if apparmor.IsEnabled() {
+               var appArmorProfile string
+               if c.AppArmorProfile != "" {
+                       appArmorProfile = c.AppArmorProfile
+               } else if c.HostConfig.Privileged {
+                       appArmorProfile = "unconfined"
+               } else {
+                       appArmorProfile = "docker-default"
+               }
+
+               if appArmorProfile == "docker-default" {
+                       // Unattended upgrades and other fun services can 
unload AppArmor
+                       // profiles inadvertently. Since we cannot store our 
profile in
+                       // /etc/apparmor.d, nor can we practically add other 
ways of
+                       // telling the system to keep our profile loaded, in 
order to make
+                       // sure that we keep the default profile enabled we 
dynamically
+                       // reload it if necessary.
+                       if err := ensureDefaultAppArmorProfile(); err != nil {
+                               return err
+                       }
+               }
+       }
        return nil
 }
-- 
2.12.0

++++++ secrets-0001-daemon-allow-directory-creation-in-run-secrets.patch ++++++
>From 0c4cf4fac76f2a5272a808665985a2e0df6af0db Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asa...@suse.de>
Date: Wed, 8 Mar 2017 12:41:54 +1100
Subject: [PATCH 1/2] daemon: allow directory creation in /run/secrets

Since FileMode can have the directory bit set, allow a SecretStore
implementation to return secrets that are actually directories. This is
useful for creating directories and subdirectories of secrets.

Backport: https://github.com/docker/docker/pull/31632
Signed-off-by: Aleksa Sarai <asa...@suse.de>
---
 daemon/container_operations_unix.go | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/daemon/container_operations_unix.go 
b/daemon/container_operations_unix.go
index 2296045765d4..8527a7907373 100644
--- a/daemon/container_operations_unix.go
+++ b/daemon/container_operations_unix.go
@@ -195,8 +195,14 @@ func (daemon *Daemon) setupSecretDir(c 
*container.Container) (setupErr error) {
                if secret == nil {
                        return fmt.Errorf("unable to get secret from secret 
store")
                }
-               if err := ioutil.WriteFile(fPath, secret.Spec.Data, 
s.File.Mode); err != nil {
-                       return errors.Wrap(err, "error injecting secret")
+               if s.File.Mode.IsDir() {
+                       if err := os.Mkdir(fPath, s.File.Mode); err != nil {
+                               return errors.Wrap(err, "error injecting secret 
dir")
+                       }
+               } else {
+                       if err := ioutil.WriteFile(fPath, secret.Spec.Data, 
s.File.Mode); err != nil {
+                               return errors.Wrap(err, "error injecting 
secret")
+                       }
                }
 
                uid, err := strconv.Atoi(s.File.UID)
-- 
2.12.0

++++++ secrets-0002-SUSE-implement-SUSE-container-secrets.patch ++++++
>From a3106907d4786ed7d624201debdd43dc41fb4b97 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asa...@suse.de>
Date: Wed, 8 Mar 2017 11:43:29 +1100
Subject: [PATCH 2/2] SUSE: implement SUSE container secrets

This allows for us to pass in host credentials to a container, allowing
for SUSEConnect to work with containers.

THIS PATCH IS NOT TO BE UPSTREAMED, DUE TO THE FACT THAT IT IS
SUSE-SPECIFIC, AND UPSTREAM DOES NOT APPROVE OF THIS CONCEPT BECAUSE IT
MAKES BUILDS NOT ENTIRELY REPRODUCIBLE.

Signed-off-by: Aleksa Sarai <asa...@suse.de>
---
 daemon/start.go        |   5 +
 daemon/suse_secrets.go | 246 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 251 insertions(+)
 create mode 100644 daemon/suse_secrets.go

diff --git a/daemon/start.go b/daemon/start.go
index 6c94fd5482d0..3c06eed778d7 100644
--- a/daemon/start.go
+++ b/daemon/start.go
@@ -146,6 +146,11 @@ func (daemon *Daemon) containerStart(container 
*container.Container, checkpoint
                return err
        }
 
+       // SUSE:secrets -- inject the SUSE secret store
+       if err := daemon.injectSuseSecretStore(container); err != nil {
+               return err
+       }
+
        spec, err := daemon.createSpec(container)
        if err != nil {
                return err
diff --git a/daemon/suse_secrets.go b/daemon/suse_secrets.go
new file mode 100644
index 000000000000..591abc998e67
--- /dev/null
+++ b/daemon/suse_secrets.go
@@ -0,0 +1,246 @@
+/*
+ * suse-secrets: patch for Docker to implement SUSE secrets
+ * Copyright (C) 2017 SUSE LLC.
+ *
+ * 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 daemon
+
+import (
+       "fmt"
+       "io/ioutil"
+       "os"
+       "path/filepath"
+       "syscall"
+
+       "github.com/Sirupsen/logrus"
+       "github.com/docker/distribution/digest"
+       "github.com/docker/docker/container"
+
+       swarmtypes "github.com/docker/docker/api/types/swarm"
+       swarmexec "github.com/docker/swarmkit/agent/exec"
+       swarmapi "github.com/docker/swarmkit/api"
+)
+
+func init() {
+       // Output to tell us in logs that SUSE:secrets is enabled.
+       logrus.Infof("SUSE:secrets :: enabled")
+}
+
+// Creating a fake file.
+type SuseFakeFile struct {
+       Path string
+       Uid  int
+       Gid  int
+       Mode os.FileMode
+       Data []byte
+}
+
+func (s SuseFakeFile) id() string {
+       return fmt.Sprintf("suse::%s:%s", digest.FromBytes(s.Data), s.Path)
+}
+
+func (s SuseFakeFile) toSecret() *swarmapi.Secret {
+       return &swarmapi.Secret{
+               ID:       s.id(),
+               Internal: true,
+               Spec: swarmapi.SecretSpec{
+                       Data: s.Data,
+               },
+       }
+}
+
+func (s SuseFakeFile) toSecretReference() *swarmtypes.SecretReference {
+       return &swarmtypes.SecretReference{
+               SecretID:   s.id(),
+               SecretName: s.id(),
+               File: &swarmtypes.SecretReferenceFileTarget{
+                       Name: s.Path,
+                       UID:  fmt.Sprintf("%d", s.Uid),
+                       GID:  fmt.Sprintf("%d", s.Gid),
+                       Mode: s.Mode,
+               },
+       }
+}
+
+// readDir will recurse into a directory prefix/dir, and return the set of 
secrets
+// in that directory. The Path attribute of each has the prefix stripped. 
Symlinks
+// are evaluated.
+func readDir(prefix, dir string) ([]*SuseFakeFile, error) {
+       var suseFiles []*SuseFakeFile
+
+       path := filepath.Join(prefix, dir)
+
+       fi, err := os.Stat(path)
+       if err != nil {
+               // Ignore dangling symlinks.
+               if os.IsNotExist(err) {
+                       logrus.Warnf("SUSE:secrets :: dangling symlink: %s", 
path)
+                       return suseFiles, nil
+               }
+               return nil, err
+       }
+
+       stat, ok := fi.Sys().(*syscall.Stat_t)
+       if !ok {
+               logrus.Warnf("SUSE:secrets :: failed to cast directory stat_t: 
defaulting to owned by root:root: %s", path)
+       }
+
+       suseFiles = append(suseFiles, &SuseFakeFile{
+               Path: dir,
+               Uid:  int(stat.Uid),
+               Gid:  int(stat.Gid),
+               Mode: fi.Mode(),
+       })
+
+       files, err := ioutil.ReadDir(path)
+       if err != nil {
+               return nil, err
+       }
+
+       for _, f := range files {
+               subpath := filepath.Join(dir, f.Name())
+
+               if f.IsDir() {
+                       secrets, err := readDir(prefix, subpath)
+                       if err != nil {
+                               return nil, err
+                       }
+                       suseFiles = append(suseFiles, secrets...)
+               } else {
+                       secrets, err := readFile(prefix, subpath)
+                       if err != nil {
+                               return nil, err
+                       }
+                       suseFiles = append(suseFiles, secrets...)
+               }
+       }
+
+       return suseFiles, nil
+}
+
+// readFile returns a secret given a file under a given prefix.
+func readFile(prefix, file string) ([]*SuseFakeFile, error) {
+       var suseFiles []*SuseFakeFile
+
+       path := filepath.Join(prefix, file)
+       fi, err := os.Stat(path)
+       if err != nil {
+               // Ignore dangling symlinks.
+               if os.IsNotExist(err) {
+                       logrus.Warnf("SUSE:secrets :: dangling symlink: %s", 
path)
+                       return suseFiles, nil
+               }
+               return nil, err
+       }
+
+       stat, ok := fi.Sys().(*syscall.Stat_t)
+       if !ok {
+               logrus.Warnf("SUSE:secrets :: failed to cast file stat_t: 
defaulting to owned by root:root: %s", path)
+       }
+
+       if fi.IsDir() {
+               secrets, err := readDir(prefix, file)
+               if err != nil {
+                       return nil, err
+               }
+               suseFiles = append(suseFiles, secrets...)
+       } else {
+               bytes, err := ioutil.ReadFile(path)
+               if err != nil {
+                       return nil, err
+               }
+               suseFiles = append(suseFiles, &SuseFakeFile{
+                       Path: file,
+                       Uid:  int(stat.Uid),
+                       Gid:  int(stat.Gid),
+                       Mode: fi.Mode(),
+                       Data: bytes,
+               })
+       }
+
+       return suseFiles, nil
+}
+
+// getHostSuseSecretData returns the list of SuseFakeFiles the need to be added
+// as SUSE secrets.
+func getHostSuseSecretData() ([]*SuseFakeFile, error) {
+       secrets := []*SuseFakeFile{}
+
+       credentials, err := readDir("/etc/zypp", "credentials.d")
+       if err != nil {
+               if os.IsNotExist(err) {
+                       credentials = []*SuseFakeFile{}
+               } else {
+                       logrus.Errorf("SUSE:secrets :: error while reading zypp 
credentials: %s", err)
+                       return nil, err
+               }
+       }
+       secrets = append(secrets, credentials...)
+
+       suseConnect, err := readFile("/etc", "SUSEConnect")
+       if err != nil {
+               if os.IsNotExist(err) {
+                       suseConnect = []*SuseFakeFile{}
+               } else {
+                       logrus.Errorf("SUSE:secrets :: error while reading 
/etc/SUSEConnect: %s", err)
+                       return nil, err
+               }
+       }
+       secrets = append(secrets, suseConnect...)
+
+       return secrets, nil
+}
+
+// In order to reduce the amount of code touched outside of this file, we
+// implement the swarm API for SecretGetter. This asserts that this requirement
+// will always be matched.
+var _ swarmexec.SecretGetter = &suseSecretGetter{}
+
+type suseSecretGetter struct {
+       dfl     swarmexec.SecretGetter
+       secrets map[string]*swarmapi.Secret
+}
+
+func (s *suseSecretGetter) Get(id string) *swarmapi.Secret {
+       logrus.Debugf("SUSE:secrets :: id=%s requested from suseSecretGetter", 
id)
+
+       secret, ok := s.secrets[id]
+       if !ok {
+               // fallthrough
+               return s.dfl.Get(id)
+       }
+
+       return secret
+}
+
+func (daemon *Daemon) injectSuseSecretStore(c *container.Container) error {
+       newSecretStore := &suseSecretGetter{
+               dfl:     c.SecretStore,
+               secrets: make(map[string]*swarmapi.Secret),
+       }
+
+       secrets, err := getHostSuseSecretData()
+       if err != nil {
+               return err
+       }
+
+       for _, secret := range secrets {
+               newSecretStore.secrets[secret.id()] = secret.toSecret()
+               c.SecretReferences = append(c.SecretReferences, 
secret.toSecretReference())
+       }
+
+       c.SecretStore = newSecretStore
+       return nil
+}
-- 
2.12.0


Reply via email to