github.com/coreos/mantle@v0.13.0/kola/tests/ostree/unlock.go (about) 1 // Copyright 2018 Red Hat, 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 ostree 16 17 import ( 18 "fmt" 19 20 "github.com/coreos/mantle/kola/cluster" 21 "github.com/coreos/mantle/kola/register" 22 "github.com/coreos/mantle/kola/tests/util" 23 "github.com/coreos/mantle/platform" 24 ) 25 26 func init() { 27 register.Register(®ister.Test{ 28 Run: ostreeUnlockTest, 29 ClusterSize: 1, 30 Name: "ostree.unlock", 31 Flags: []register.Flag{register.RequiresInternetAccess}, // need network to pull RPM 32 Distros: []string{"fcos", "rhcos"}, 33 FailFast: true, 34 }) 35 register.Register(®ister.Test{ 36 Run: ostreeHotfixTest, 37 ClusterSize: 1, 38 Flags: []register.Flag{register.RequiresInternetAccess}, // need network to pull RPM 39 Name: "ostree.hotfix", 40 Distros: []string{"fcos", "rhcos"}, 41 FailFast: true, 42 }) 43 44 } 45 46 var ( 47 rpmUrl string = "https://raw.githubusercontent.com/projectatomic/atomic-host-tests/master/rpm/aht-dummy-1.0-1.noarch.rpm" 48 rpmName string = "aht-dummy" 49 ) 50 51 // ostreeAdminUnlock will unlock the deployment and verify the success of the operation 52 func ostreeAdminUnlock(c cluster.TestCluster, m platform.Machine, hotfix bool) error { 53 var unlockCmd string = "sudo ostree admin unlock" 54 if hotfix { 55 unlockCmd = "sudo ostree admin unlock --hotfix" 56 } 57 58 _, unlockCmdErr := c.SSH(m, unlockCmd) 59 if unlockCmdErr != nil { 60 return fmt.Errorf(`Failed to unlock deployment: %v`, unlockCmdErr) 61 } 62 63 status, err := util.GetRpmOstreeStatusJSON(c, m) 64 if err != nil { 65 c.Fatal(err) 66 } 67 68 if len(status.Deployments) < 1 { 69 c.Fatalf(`Did not find any deployments`) 70 } 71 72 // verify that the unlock was successful 73 if hotfix && status.Deployments[0].Unlocked != "hotfix" { 74 return fmt.Errorf(`Hotfix mode is not reflected in "rpm-ostree status"; got: %q`, status.Deployments[0].Unlocked) 75 } 76 77 if !hotfix && status.Deployments[0].Unlocked != "development" { 78 return fmt.Errorf(`Unlocked mode is not reflected in "rpm-ostree status"; got: %q`, status.Deployments[0].Unlocked) 79 } 80 81 return nil 82 } 83 84 // rpmInstallVerify is a small utility func to handle installing an RPM 85 // and verifying the install was successful 86 // NOTE: RPM name and binary name must match 87 func rpmInstallVerify(c cluster.TestCluster, m platform.Machine, rpmFile string, rpmName string) error { 88 _, installErr := c.SSH(m, ("sudo rpm -i " + rpmFile)) 89 if installErr != nil { 90 return fmt.Errorf(`Failed to install RPM: %v`, installErr) 91 } 92 93 _, cmdErr := c.SSH(m, ("command -v " + rpmName)) 94 if cmdErr != nil { 95 return fmt.Errorf(`Failed to find binary: %v`, cmdErr) 96 } 97 98 _, rpmErr := c.SSH(m, ("rpm -q " + rpmName)) 99 if rpmErr != nil { 100 return fmt.Errorf(`Failed to find RPM in rpmdb: %v`, rpmErr) 101 } 102 103 return nil 104 } 105 106 // rpmUninstallVerify is a small utility func to handle uninstalling an RPM 107 // and verifying the uninstall was successful 108 // NOTE: RPM name and binary name must match 109 func rpmUninstallVerify(c cluster.TestCluster, m platform.Machine, rpmName string) error { 110 _, uninstallErr := c.SSH(m, ("sudo rpm -e " + rpmName)) 111 if uninstallErr != nil { 112 return fmt.Errorf(`Failed to uninstall RPM: %v`, uninstallErr) 113 } 114 115 _, missCmdErr := c.SSH(m, ("command -v " + rpmName)) 116 if missCmdErr == nil { 117 return fmt.Errorf(`Found a binary that should not be there: %v`, missCmdErr) 118 } 119 120 _, missRpmErr := c.SSH(m, ("rpm -q " + rpmName)) 121 if missRpmErr == nil { 122 return fmt.Errorf(`RPM incorrectly in rpmdb after RPM uninstall: %v`, missRpmErr) 123 } 124 125 return nil 126 } 127 128 // ostreeUnlockTest verifies the simplest use of `ostree admin unlock` by 129 // trying to install a dummy RPM on the host, rebooting, and ensuring 130 // the RPM is gone after reboot 131 func ostreeUnlockTest(c cluster.TestCluster) { 132 m := c.Machines()[0] 133 134 // unlock the deployment 135 c.Run("unlock", func(c cluster.TestCluster) { 136 unlockErr := ostreeAdminUnlock(c, m, false) 137 if unlockErr != nil { 138 c.Fatal(unlockErr) 139 } 140 }) 141 142 // try to install an RPM via HTTP 143 c.Run("install", func(c cluster.TestCluster) { 144 rpmInstallErr := rpmInstallVerify(c, m, rpmUrl, rpmName) 145 if rpmInstallErr != nil { 146 c.Fatal(rpmInstallErr) 147 } 148 }) 149 150 // try to uninstall RPM 151 c.Run("uninstall", func(c cluster.TestCluster) { 152 rpmUninstallErr := rpmUninstallVerify(c, m, rpmName) 153 if rpmUninstallErr != nil { 154 c.Fatal(rpmUninstallErr) 155 } 156 }) 157 158 // re-install the RPM and verify the unlocked deployment is discarded 159 // after reboot 160 c.Run("discard", func(c cluster.TestCluster) { 161 c.MustSSH(m, ("sudo rpm -i " + rpmUrl)) 162 163 unlockRebootErr := m.Reboot() 164 if unlockRebootErr != nil { 165 c.Fatalf("Failed to reboot machine: %v", unlockRebootErr) 166 } 167 168 ros, err := util.GetRpmOstreeStatusJSON(c, m) 169 if err != nil { 170 c.Fatal(err) 171 } 172 173 if ros.Deployments[0].Unlocked != "none" { 174 c.Fatalf(`Deployment was incorrectly unlocked; got: %q`, ros.Deployments[0].Unlocked) 175 } 176 177 _, secCmdErr := c.SSH(m, ("command -v " + rpmName)) 178 if secCmdErr == nil { 179 c.Fatalf(`Binary was incorrectly found after reboot`) 180 } 181 _, secRpmErr := c.SSH(m, ("rpm -q " + rpmName)) 182 if secRpmErr == nil { 183 c.Fatalf(`RPM incorrectly in rpmdb after reboot`) 184 } 185 }) 186 } 187 188 // ostreeHotfixTest verifies that the deployment can be put into "hotfix" 189 // mode, where the RPMs installed will persist across reboots. A rollback will 190 // return the host to the original state 191 func ostreeHotfixTest(c cluster.TestCluster) { 192 m := c.Machines()[0] 193 194 // unlock the deployment into "hotfix" mode 195 c.Run("unlock", func(c cluster.TestCluster) { 196 unlockErr := ostreeAdminUnlock(c, m, true) 197 if unlockErr != nil { 198 c.Fatal(unlockErr) 199 } 200 }) 201 202 // try to install an RPM via HTTP 203 c.Run("install", func(c cluster.TestCluster) { 204 rpmInstallErr := rpmInstallVerify(c, m, rpmUrl, rpmName) 205 if rpmInstallErr != nil { 206 c.Fatal(rpmInstallErr) 207 } 208 }) 209 210 // uninstall the RPM 211 c.Run("uninstall", func(c cluster.TestCluster) { 212 rpmUninstallErr := rpmUninstallVerify(c, m, rpmName) 213 if rpmUninstallErr != nil { 214 c.Fatal(rpmUninstallErr) 215 } 216 }) 217 218 // install the RPM again, reboot, verify it the "hotfix" deployment 219 // and RPM have persisted 220 c.Run("persist", func(c cluster.TestCluster) { 221 c.MustSSH(m, ("sudo rpm -i " + rpmUrl)) 222 223 unlockRebootErr := m.Reboot() 224 if unlockRebootErr != nil { 225 c.Fatalf("Failed to reboot machine: %v", unlockRebootErr) 226 } 227 228 ros, err := util.GetRpmOstreeStatusJSON(c, m) 229 if err != nil { 230 c.Fatal(err) 231 } 232 233 if ros.Deployments[0].Unlocked != "hotfix" { 234 c.Fatalf(`Hotfix mode was not detected; got: %q`, ros.Deployments[0].Unlocked) 235 } 236 237 c.MustSSH(m, ("command -v " + rpmName)) 238 239 c.MustSSH(m, ("rpm -q " + rpmName)) 240 }) 241 242 // roll back the deployment and verify the "hotfix" is no longer present 243 c.Run("rollback", func(c cluster.TestCluster) { 244 c.MustSSH(m, "sudo rpm-ostree rollback") 245 246 rollbackRebootErr := m.Reboot() 247 if rollbackRebootErr != nil { 248 c.Fatalf("Failed to reboot machine: %v", rollbackRebootErr) 249 } 250 251 rollbackStatus, err := util.GetRpmOstreeStatusJSON(c, m) 252 if err != nil { 253 c.Fatal(err) 254 } 255 256 if rollbackStatus.Deployments[0].Unlocked != "none" { 257 c.Fatalf(`Rollback did not remove hotfix mode; got: $q`, rollbackStatus.Deployments[0].Unlocked) 258 } 259 260 _, secCmdErr := c.SSH(m, ("command -v " + rpmName)) 261 if secCmdErr == nil { 262 c.Fatalf(`Binary was incorrectly found after reboot`) 263 } 264 _, secRpmErr := c.SSH(m, ("rpm -q " + rpmName)) 265 if secRpmErr == nil { 266 c.Fatalf(`RPM incorrectly in rpmdb after reboot`) 267 } 268 }) 269 }