diff --git a/.github/workflows/PR-wip-checks.yaml b/.github/workflows/PR-wip-checks.yaml new file mode 100644 index 0000000000..16f8167b2b --- /dev/null +++ b/.github/workflows/PR-wip-checks.yaml @@ -0,0 +1,21 @@ +name: Pull request WIP checks +on: + pull_request: + types: + - opened + - synchronize + - reopened + - edited + - labeled + - unlabeled + +jobs: + pr_wip_check: + runs-on: ubuntu-latest + name: WIP Check + steps: + - name: WIP Check + uses: tim-actions/wip-check@1c2a1ca6c110026b3e2297bb2ef39e1747b5a755 + with: + labels: '["do-not-merge", "wip", "rfc"]' + keywords: '["WIP", "wip", "RFC", "rfc", "dnm", "DNM", "do-not-merge"]' diff --git a/.github/workflows/dco-check.yaml b/.github/workflows/dco-check.yaml new file mode 100644 index 0000000000..159dec2e1a --- /dev/null +++ b/.github/workflows/dco-check.yaml @@ -0,0 +1,22 @@ +name: DCO check +on: + pull_request: + types: + - opened + - reopened + - synchronize + +jobs: + dco_check_job: + runs-on: ubuntu-latest + name: DCO Check + steps: + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@ed97a21c3f83c3417e67a4733ea76887293a2c8f + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@2fd0504dc0d27b33f542867c300c60840c6dcb20 + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} diff --git a/ci/lib.sh b/ci/lib.sh index 76734f1f55..e40e696501 100644 --- a/ci/lib.sh +++ b/ci/lib.sh @@ -16,6 +16,10 @@ clone_tests_repo() fi go get -d -u "$tests_repo" || true + + if [ -n "${TRAVIS_BRANCH:-}" ]; then + ( cd "${tests_repo_dir}" && git checkout "${TRAVIS_BRANCH}" ) + fi } run_static_checks() diff --git a/src/agent/src/device.rs b/src/agent/src/device.rs index 775ead87db..423fc9abbb 100644 --- a/src/agent/src/device.rs +++ b/src/agent/src/device.rs @@ -398,7 +398,7 @@ pub fn update_device_cgroup(spec: &mut Spec) -> Result<()> { major: Some(major), minor: Some(minor), r#type: String::from("b"), - access: String::from("rwm"), + access: String::from("rw"), }); Ok(()) diff --git a/src/runtime/virtcontainers/sandbox.go b/src/runtime/virtcontainers/sandbox.go index 82e0a3ac12..c7cfedb574 100644 --- a/src/runtime/virtcontainers/sandbox.go +++ b/src/runtime/virtcontainers/sandbox.go @@ -1,4 +1,5 @@ // Copyright (c) 2016 Intel Corporation +// Copyright (c) 2020 Adobe Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -1201,6 +1202,14 @@ func (s *Sandbox) CreateContainer(contConfig ContainerConfig) (VCContainer, erro defer func() { // Rollback if error happens. if err != nil { + logger := s.Logger().WithFields(logrus.Fields{"container-id": c.id, "sandox-id": s.id, "rollback": true}) + logger.Warning("Cleaning up partially created container") + + if err2 := c.stop(true); err2 != nil { + logger.WithError(err2).Warning("Could not delete container") + } + + logger.Debug("Removing stopped container from sandbox store") s.removeContainer(c.id) } }() diff --git a/src/runtime/virtcontainers/sandbox_test.go b/src/runtime/virtcontainers/sandbox_test.go index d2ec1920ad..4af47ffaec 100644 --- a/src/runtime/virtcontainers/sandbox_test.go +++ b/src/runtime/virtcontainers/sandbox_test.go @@ -169,215 +169,6 @@ func TestCreateSandboxEmptyID(t *testing.T) { defer cleanUp() } -func testSandboxStateTransition(t *testing.T, state types.StateString, newState types.StateString) error { - hConfig := newHypervisorConfig(nil, nil) - - p, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NetworkConfig{}, nil, nil) - assert.NoError(t, err) - defer cleanUp() - - p.state = types.SandboxState{ - State: state, - } - - return p.state.ValidTransition(state, newState) -} - -func TestSandboxStateReadyRunning(t *testing.T) { - err := testSandboxStateTransition(t, types.StateReady, types.StateRunning) - assert.NoError(t, err) -} - -func TestSandboxStateRunningPaused(t *testing.T) { - err := testSandboxStateTransition(t, types.StateRunning, types.StatePaused) - assert.NoError(t, err) -} - -func TestSandboxStatePausedRunning(t *testing.T) { - err := testSandboxStateTransition(t, types.StatePaused, types.StateRunning) - assert.NoError(t, err) -} - -func TestSandboxStatePausedStopped(t *testing.T) { - err := testSandboxStateTransition(t, types.StatePaused, types.StateStopped) - assert.NoError(t, err) -} - -func TestSandboxStateRunningStopped(t *testing.T) { - err := testSandboxStateTransition(t, types.StateRunning, types.StateStopped) - assert.NoError(t, err) -} - -func TestSandboxStateReadyPaused(t *testing.T) { - err := testSandboxStateTransition(t, types.StateReady, types.StateStopped) - assert.NoError(t, err) -} - -func TestSandboxStatePausedReady(t *testing.T) { - err := testSandboxStateTransition(t, types.StateStopped, types.StateReady) - assert.Error(t, err) -} - -func testStateValid(t *testing.T, stateStr types.StateString, expected bool) { - state := &types.SandboxState{ - State: stateStr, - } - - ok := state.Valid() - assert.Equal(t, ok, expected) -} - -func TestStateValidSuccessful(t *testing.T) { - testStateValid(t, types.StateReady, true) - testStateValid(t, types.StateRunning, true) - testStateValid(t, types.StatePaused, true) - testStateValid(t, types.StateStopped, true) -} - -func TestStateValidFailing(t *testing.T) { - testStateValid(t, "", false) -} - -func TestValidTransitionFailingOldStateMismatch(t *testing.T) { - state := &types.SandboxState{ - State: types.StateReady, - } - - err := state.ValidTransition(types.StateRunning, types.StateStopped) - assert.Error(t, err) -} - -func TestVolumesSetSuccessful(t *testing.T) { - volumes := &types.Volumes{} - - volStr := "mountTag1:hostPath1 mountTag2:hostPath2" - - expected := types.Volumes{ - { - MountTag: "mountTag1", - HostPath: "hostPath1", - }, - { - MountTag: "mountTag2", - HostPath: "hostPath2", - }, - } - - err := volumes.Set(volStr) - assert.NoError(t, err) - assert.Exactly(t, *volumes, expected) -} - -func TestVolumesSetFailingTooFewArguments(t *testing.T) { - volumes := &types.Volumes{} - - volStr := "mountTag1 mountTag2" - - err := volumes.Set(volStr) - assert.Error(t, err) -} - -func TestVolumesSetFailingTooManyArguments(t *testing.T) { - volumes := &types.Volumes{} - - volStr := "mountTag1:hostPath1:Foo1 mountTag2:hostPath2:Foo2" - - err := volumes.Set(volStr) - assert.Error(t, err) -} - -func TestVolumesSetFailingVoidArguments(t *testing.T) { - volumes := &types.Volumes{} - - volStr := ": : :" - - err := volumes.Set(volStr) - assert.Error(t, err) -} - -func TestVolumesStringSuccessful(t *testing.T) { - volumes := &types.Volumes{ - { - MountTag: "mountTag1", - HostPath: "hostPath1", - }, - { - MountTag: "mountTag2", - HostPath: "hostPath2", - }, - } - - expected := "mountTag1:hostPath1 mountTag2:hostPath2" - - result := volumes.String() - assert.Equal(t, result, expected) -} - -func TestSocketsSetSuccessful(t *testing.T) { - sockets := &types.Sockets{} - - sockStr := "devID1:id1:hostPath1:Name1 devID2:id2:hostPath2:Name2" - - expected := types.Sockets{ - { - DeviceID: "devID1", - ID: "id1", - HostPath: "hostPath1", - Name: "Name1", - }, - { - DeviceID: "devID2", - ID: "id2", - HostPath: "hostPath2", - Name: "Name2", - }, - } - - err := sockets.Set(sockStr) - assert.NoError(t, err) - assert.Exactly(t, *sockets, expected) -} - -func TestSocketsSetFailingWrongArgsAmount(t *testing.T) { - sockets := &types.Sockets{} - - sockStr := "devID1:id1:hostPath1" - - err := sockets.Set(sockStr) - assert.Error(t, err) -} - -func TestSocketsSetFailingVoidArguments(t *testing.T) { - sockets := &types.Sockets{} - - sockStr := ":::" - - err := sockets.Set(sockStr) - assert.Error(t, err) -} - -func TestSocketsStringSuccessful(t *testing.T) { - sockets := &types.Sockets{ - { - DeviceID: "devID1", - ID: "id1", - HostPath: "hostPath1", - Name: "Name1", - }, - { - DeviceID: "devID2", - ID: "id2", - HostPath: "hostPath2", - Name: "Name2", - }, - } - - expected := "devID1:id1:hostPath1:Name1 devID2:id2:hostPath2:Name2" - - result := sockets.String() - assert.Equal(t, result, expected) -} - func TestSandboxListSuccessful(t *testing.T) { sandbox := &Sandbox{} diff --git a/src/runtime/virtcontainers/types/sandbox_test.go b/src/runtime/virtcontainers/types/sandbox_test.go new file mode 100644 index 0000000000..05075e4495 --- /dev/null +++ b/src/runtime/virtcontainers/types/sandbox_test.go @@ -0,0 +1,238 @@ +// Copyright (c) 2020 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// + +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func testSandboxStateTransition(t *testing.T, state StateString, newState StateString) error { + s := SandboxState{ + State: state, + } + + return s.ValidTransition(state, newState) +} + +func TestSandboxStateReadyRunning(t *testing.T) { + err := testSandboxStateTransition(t, StateReady, StateRunning) + assert.NoError(t, err) +} + +func TestSandboxStateRunningPaused(t *testing.T) { + err := testSandboxStateTransition(t, StateRunning, StatePaused) + assert.NoError(t, err) +} + +func TestSandboxStatePausedRunning(t *testing.T) { + err := testSandboxStateTransition(t, StatePaused, StateRunning) + assert.NoError(t, err) +} + +func TestSandboxStatePausedStopped(t *testing.T) { + err := testSandboxStateTransition(t, StatePaused, StateStopped) + assert.NoError(t, err) +} + +func TestSandboxStateRunningStopped(t *testing.T) { + err := testSandboxStateTransition(t, StateRunning, StateStopped) + assert.NoError(t, err) +} + +func TestSandboxStateReadyStopped(t *testing.T) { + err := testSandboxStateTransition(t, StateReady, StateStopped) + assert.NoError(t, err) +} + +func TestSandboxStateStoppedRunning(t *testing.T) { + err := testSandboxStateTransition(t, StateStopped, StateRunning) + assert.NoError(t, err) +} + +func TestSandboxStateStoppedReady(t *testing.T) { + err := testSandboxStateTransition(t, StateStopped, StateReady) + assert.Error(t, err) +} + +func testStateValid(t *testing.T, stateStr StateString, expected bool) { + state := &SandboxState{ + State: stateStr, + } + + ok := state.Valid() + assert.Equal(t, ok, expected) +} + +func TestStateValidSuccessful(t *testing.T) { + testStateValid(t, StateReady, true) + testStateValid(t, StateRunning, true) + testStateValid(t, StatePaused, true) + testStateValid(t, StateStopped, true) +} + +func TestStateValidFailing(t *testing.T) { + testStateValid(t, "", false) +} + +func TestValidTransitionFailingOldStateMismatch(t *testing.T) { + state := &SandboxState{ + State: StateReady, + } + + err := state.ValidTransition(StateRunning, StateStopped) + assert.Error(t, err) +} + +func TestVolumesSetSuccessful(t *testing.T) { + volumes := &Volumes{} + + volStr := "mountTag1:hostPath1 mountTag2:hostPath2" + + expected := Volumes{ + { + MountTag: "mountTag1", + HostPath: "hostPath1", + }, + { + MountTag: "mountTag2", + HostPath: "hostPath2", + }, + } + + err := volumes.Set(volStr) + assert.NoError(t, err) + assert.Exactly(t, *volumes, expected) +} + +func TestVolumesSetFailingEmptyString(t *testing.T) { + volumes := &Volumes{} + + volStr := "" + + err := volumes.Set(volStr) + assert.Error(t, err) +} + +func TestVolumesSetFailingTooFewArguments(t *testing.T) { + volumes := &Volumes{} + + volStr := "mountTag1 mountTag2" + + err := volumes.Set(volStr) + assert.Error(t, err) +} + +func TestVolumesSetFailingTooManyArguments(t *testing.T) { + volumes := &Volumes{} + + volStr := "mountTag1:hostPath1:Foo1 mountTag2:hostPath2:Foo2" + + err := volumes.Set(volStr) + assert.Error(t, err) +} + +func TestVolumesSetFailingVoidArguments(t *testing.T) { + volumes := &Volumes{} + + volStr := ": : :" + + err := volumes.Set(volStr) + assert.Error(t, err) +} + +func TestVolumesStringSuccessful(t *testing.T) { + volumes := &Volumes{ + { + MountTag: "mountTag1", + HostPath: "hostPath1", + }, + { + MountTag: "mountTag2", + HostPath: "hostPath2", + }, + } + + expected := "mountTag1:hostPath1 mountTag2:hostPath2" + + result := volumes.String() + assert.Equal(t, result, expected) +} + +func TestSocketsSetSuccessful(t *testing.T) { + sockets := &Sockets{} + + sockStr := "devID1:id1:hostPath1:Name1 devID2:id2:hostPath2:Name2" + + expected := Sockets{ + { + DeviceID: "devID1", + ID: "id1", + HostPath: "hostPath1", + Name: "Name1", + }, + { + DeviceID: "devID2", + ID: "id2", + HostPath: "hostPath2", + Name: "Name2", + }, + } + + err := sockets.Set(sockStr) + assert.NoError(t, err) + assert.Exactly(t, *sockets, expected) +} + +func TestSocketsSetFailingEmptyString(t *testing.T) { + sockets := &Sockets{} + + sockStr := "" + + err := sockets.Set(sockStr) + assert.Error(t, err) +} + +func TestSocketsSetFailingWrongArgsAmount(t *testing.T) { + sockets := &Sockets{} + + sockStr := "devID1:id1:hostPath1" + + err := sockets.Set(sockStr) + assert.Error(t, err) +} + +func TestSocketsSetFailingVoidArguments(t *testing.T) { + sockets := &Sockets{} + + sockStr := ":::" + + err := sockets.Set(sockStr) + assert.Error(t, err) +} + +func TestSocketsStringSuccessful(t *testing.T) { + sockets := &Sockets{ + { + DeviceID: "devID1", + ID: "id1", + HostPath: "hostPath1", + Name: "Name1", + }, + { + DeviceID: "devID2", + ID: "id2", + HostPath: "hostPath2", + Name: "Name2", + }, + } + + expected := "devID1:id1:hostPath1:Name1 devID2:id2:hostPath2:Name2" + + result := sockets.String() + assert.Equal(t, result, expected) +}