github.com/coreos/mantle@v0.13.0/kola/tests/rkt/rkt.go (about)

     1  // Copyright 2016 CoreOS, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rkt
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"strings"
    21  	"time"
    22  
    23  	"github.com/coreos/mantle/kola/cluster"
    24  	"github.com/coreos/mantle/kola/register"
    25  	"github.com/coreos/mantle/platform"
    26  	"github.com/coreos/mantle/platform/conf"
    27  	"github.com/coreos/mantle/util"
    28  )
    29  
    30  var config = conf.Ignition(`{
    31  	"ignition": {
    32  		"version": "2.0.0"
    33  	},
    34  	"systemd": {
    35  		"units": [{
    36  			"name": "etcd-member.service",
    37  			"enable": true
    38  		}]
    39  	}
    40  }`)
    41  
    42  func init() {
    43  	register.Register(&register.Test{
    44  		Name:        "cl.rkt.etcd3",
    45  		Run:         rktEtcd,
    46  		ClusterSize: 1,
    47  		Flags:       []register.Flag{register.RequiresInternetAccess}, // etcdctl health-check requires networking
    48  		Distros:     []string{"cl"},
    49  		UserData:    config,
    50  	})
    51  
    52  	register.Register(&register.Test{
    53  		Name:        "rkt.base",
    54  		ClusterSize: 1,
    55  		Run:         rktBase,
    56  		Distros:     []string{"cl"},
    57  	})
    58  
    59  }
    60  
    61  func rktEtcd(c cluster.TestCluster) {
    62  	m := c.Machines()[0]
    63  
    64  	etcdCmd := "etcdctl cluster-health"
    65  	etcdCheck := func() error {
    66  		output, err := c.SSH(m, etcdCmd)
    67  		if err != nil {
    68  			return fmt.Errorf("failed to run %q: output: %q status: %q", etcdCmd, output, err)
    69  		}
    70  
    71  		return nil
    72  	}
    73  
    74  	if err := util.Retry(60, 3*time.Second, etcdCheck); err != nil {
    75  		c.Fatalf("etcd in rkt failed health check: %v", err)
    76  	}
    77  }
    78  
    79  // we use subtests to improve testing performance here. Creating the aci is
    80  // more expensive than actually running most of these tests.
    81  func rktBase(c cluster.TestCluster) {
    82  	m := c.Machines()[0]
    83  
    84  	// TODO this should not be necessary, but is at the time of writing
    85  	c.MustSSH(m, "sudo setenforce 0")
    86  
    87  	createTestAci(c, m, "test.rkt.aci", []string{"echo", "sleep", "sh"})
    88  
    89  	journalForPodContains := func(c cluster.TestCluster, uuidFile string, contains string) {
    90  		output := c.MustSSH(m, fmt.Sprintf("journalctl --dir /var/log/journal/$(cat %s | sed 's/-//g')", uuidFile))
    91  		if !bytes.Contains(output, []byte(contains)) {
    92  			c.Fatalf("expected journal logs from machine dir to include app output %q; was %s", contains, output)
    93  		}
    94  	}
    95  
    96  	c.Run("cli", func(c cluster.TestCluster) {
    97  		uuidFile := "/tmp/run-test.uuid"
    98  
    99  		output := c.MustSSH(m, fmt.Sprintf("sudo rkt run --uuid-file-save=%s test.rkt.aci:latest --exec=sh -- -c 'echo success'", uuidFile))
   100  		defer c.SSH(m, fmt.Sprintf("sudo rkt rm --uuid-file=%s", uuidFile))
   101  
   102  		if !bytes.Contains(output, []byte("success")) {
   103  			c.Fatalf("expected rkt stdout to include app output ('success'); was %s", output)
   104  		}
   105  
   106  		journalForPodContains(c, uuidFile, "success")
   107  	})
   108  
   109  	c.Run("unit", func(c cluster.TestCluster) {
   110  		uuidFile := "/tmp/run-as-unit-test.uuid"
   111  
   112  		c.MustSSH(m, fmt.Sprintf("sudo systemd-run --quiet --unit run-as-unit.service -- rkt run --uuid-file-save=%s test.rkt.aci:latest --exec=sh -- -c 'echo success'", uuidFile))
   113  		defer c.SSH(m, fmt.Sprintf("sudo rkt rm --uuid-file=%s", uuidFile))
   114  
   115  		c.MustSSH(m, fmt.Sprintf("while ! [ -s %s ]; do sleep 0.1; done; rkt status --wait $(cat %s)", uuidFile, uuidFile))
   116  
   117  		journalForPodContains(c, uuidFile, "success")
   118  	})
   119  
   120  	c.Run("machinectl-integration", func(c cluster.TestCluster) {
   121  		uuidFile := "/tmp/run-machinectl.uuid"
   122  
   123  		c.MustSSH(m, fmt.Sprintf("sudo systemd-run --quiet --unit run-machinectl -- rkt run --uuid-file-save=%s test.rkt.aci:latest --exec=sleep -- inf", uuidFile))
   124  		defer c.SSH(m, fmt.Sprintf("sudo rkt rm --uuid-file=%s", uuidFile))
   125  
   126  		c.MustSSH(m, fmt.Sprintf("while ! [ -s %s ]; do sleep 0.1; done; rkt status --wait-ready $(cat %s)", uuidFile, uuidFile))
   127  
   128  		machinectlOutput := c.MustSSH(m, fmt.Sprintf("machinectl show rkt-$(cat %s)", uuidFile))
   129  
   130  		for _, line := range []string{"State=running", "Class=container", "Service=rkt"} {
   131  			if !bytes.Contains(machinectlOutput, []byte(line)) {
   132  				c.Fatalf("expected machinectl to include %q: was %s", line, machinectlOutput)
   133  			}
   134  		}
   135  
   136  		c.MustSSH(m, fmt.Sprintf("sudo rkt stop --uuid-file=%s", uuidFile))
   137  		c.MustSSH(m, fmt.Sprintf("rkt status --wait $(cat %s)", uuidFile))
   138  	})
   139  }
   140  
   141  // TODO: once rkt can fetch a local 'docker' image, using `genDockerContainer`
   142  // from the docker test file could be a better solution.
   143  func createTestAci(c cluster.TestCluster, m platform.Machine, name string, bins []string) {
   144  	// Has format strings for:
   145  	// 1) aci name
   146  	// 2) arch
   147  	testAciManifest := `{
   148  	"acKind": "ImageManifest",
   149  	"acVersion": "0.8.9",
   150  	"name": "%s",
   151  	"labels": [{"name": "os","value": "linux"},{"name": "arch","value": "amd64"},{"name": "version","value": "latest"}]
   152  }`
   153  
   154  	c.MustSSH(m, `set -e
   155  	tmpdir=$(mktemp -d)
   156  	cd $tmpdir
   157  	cat > manifest <<EOF
   158  `+fmt.Sprintf(testAciManifest, name)+`
   159  EOF
   160  
   161  	mkdir rootfs
   162  	bins=$(which `+strings.Join(bins, " ")+`)
   163  	libs=$(sudo ldd $bins | grep -o /lib'[^ ]*' | sort -u)
   164  	sudo rsync -av --relative --copy-links $bins $libs ./rootfs/
   165  
   166  	sudo tar cf /tmp/test-aci.aci .
   167  	sudo rkt image fetch --insecure-options=image /tmp/test-aci.aci
   168  	cd
   169  	sudo rm -rf /tmp/test-aci.aci $tmpdir`)
   170  }