Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal]Add more E2E test cases for sealer #1966

Open
zhy76 opened this issue Jan 10, 2023 · 1 comment
Open

[Proposal]Add more E2E test cases for sealer #1966

zhy76 opened this issue Jan 10, 2023 · 1 comment
Labels
kind/feature Category issues or PRs related to feature request

Comments

@zhy76
Copy link
Member

zhy76 commented Jan 10, 2023

Issue Description

Type: feature request

We open this issue to track and summarize cases of E2E test. Suggestions and additions to this issue are welcomed!

Describe what feature you want

Our E2E test cases are currently very limited, we need add more cases.

Additional context

E2E test task list:

sealer image:

  1. build: build a Sealer Image from a Kubefile
    • [P0]build with image type
      • Support sealer build --type app-installer with app definition
      • Support sealer build --type app-installer with kubernetes and app definition, and the image should not include the kubernetes-related resource
      • Support sealer build --type kube-installer with kubernetes and app definition
      • Support sealer build --type kube-installer with only kubernetes definition
      • Support sealer build --type kube-installer with kubernetes and cmds definition
      • If sealer build --type app-installer without app definition, return an error
      • If the Kubefile contains both LAUNCH and CMDS, return an error
    • [P1]build without cache
    • build with args
    • [P1]build multi-platform image
    • [P0]instructions of Kubefile
      • cluster image
      • app image
  2. images: list all Sealer Images on the local node
    • [P0]List Sealer images information
  3. inspect: print the image information or Clusterfile
    • [P0]Support get image type and install cmd info from the result
    • [P0]Sealer inspect by image name
    • [P0]Sealer inspect by image ID
  4. load: load a Sealer Image from a tar file
    • [P1]Load a Sealer Image from a tar file
  5. login: login image registry
    • Login a remote registry
    • [P2]Login a local registry
  6. logout: logout from image registry
    • Logout a remote registry
    • [P2]Logout a local registry
  7. pull: pull Sealer Image from a registry to local
    • Pull Sealer Image from a registry to local
  8. push: push Sealer Image to remote registry
    • Push Sealer Image to remote registry
    • [P2]Push Sealer Image to local registry
  9. rmi: remove local images
    • Remove local images
    • [P2]prune dangling images
  10. save: save Sealer Image to a tar file
    • [P2]Save Sealer Image to a tar file
  11. tag: create one or more tags for local Sealer Image
    • Create one or more tags for local Sealer Image

sealer cluster:

  1. cert: Update Kubernetes API server's cert
    • [P1]add DNS domain or IP in certs, if it is already in the cert subject alternative names list, nothing will be changed
  2. delete: delete an existing cluster
    • Succeed in deleting the whole cluster (delete all)
    • Succeed in deleting one node
    • [P0]Succeed in deleting one master
    • [P0]Succeed in deleting node IP list expressed in range form
  3. apply: apply a Kubernetes cluster via specified Clusterfile
    • Succeed in applying a kube-installer type image by Clusterfile
    • [P0]Succeed in applying a kube-installer type image by Clusterfile with Plugin
      • Plugin type: shell plugin.
      • [P0]Scope:
        • on master0: pre-install, post-install, pre-uninstall, post-uninstall, pre-scaleup, post-scaleup
        • on host: pre-init-host, post-init-host, pre-clean-host, post-clean-host
    • Sealer executes machine is master0
    • [P0]Sealer executes machine is not master0
  4. scale-up: scale-up new master or worker node to specified cluster
    • [P0]Succeed in joining a node
    • [P0]Succeed in joining a master
    • [P0]Succeed in joining node IP list expressed in range form
  5. join: join new master or worker node to specified cluster
    • Succeed in joining a node
    • [P0]Succeed in joining a master
    • [P0]Succeed in joining node IP list expressed in range form
  6. run: start to run a cluster from a Sealer Image
    • Succeed in running a kube-installer type image and ensuring the kubernetes created and app launched/cmds executed successfully
    • [P0]Succeed in running a kube-installer type image by Clusterfile
    • [P0]Succeed in running an app-installer type image and ensuring the app launched successfully
    • [P1]No vendor lock-in k8s: support run an app-installer type image on any kubernetes cluster even if they are not created by sealer
    • [P0] Supports parallel deployment of apps
    • [P1]LAUNCH one of app for app images
    • [P1]Sealer run-app
      • Only run app for KubeImage and check the status of kubenetes
      • Run app image for AppImage
    • [P0]Support single-node/3-node/3+N-node deployment mode
    • [P1]Support AirGap environment deployment
    • [P2]Support for multi kubernetes versions
    • [P2]Support ipv6 single stack, ipv6 dual stack deployment
    • [P1]Support ssh key deployment cluster
    • [P0]Support node IP list expressed in range form
    • [P1]If the node has a corresponding kubelet/docker, will refuse install
    • [P2]Supports host aliases
    • [P2]CIDR validity check
    • [P1]Support configure LimitNOFILE for docker.service
    • [P1]If the deployment fails at a certain step, the deployment can continue from the breakpoint again. This feature does not require that all breakpoints can be continued, but at least the following points are supported:
      • The installation file has been distributed to each node, but K8sRuntime failed, you can continue from here without the need to distribute the file again
    • [P2]Support for different container runtimes:
      • docker (19.03)
      • nvidia-docker when GPU detected
      • containerd
      • customize container runtime
    • [P1]Operation capabilities:
      • Support incremental configuration of CertSANs to existing clusters
      • Master0 can be replaced
      • Supports incremental deployment of AppImage, and can repeatedly deploy different versions of AppImage

sealer alpha:

  1. check: check the state of cluster
    • [P1]Check the status of the cluster after it is created
    • [P1]Check dependencies before cluster creation
  2. debug: Create debugging sessions for pods and nodes
    • [P2]Clean the debug container or pod
    • [P2]Debug node
    • [P2]Debug pod or container
    • [P2]List default images
    • [P2]Check items, such as network, volume.
    • [P2]Set environment variables in the container. (default [])
    • [P2]Set container image to use for debug container
    • [P2]Set container image pull policy, default policy is IfNotPresent
    • [P2]Set container name to use for debug container
    • [P2]Set namespace of Pod. (default "default")
    • [P2]Keep stdin open on the container, even if nothing is attached.
    • [P2]Allocate a TTY for the debugging container.
  3. exec: Exec a shell command or script on a specified node
    • [P1]Exec the default cluster node
    • [P1]specify the cluster name
    • [P1]using role label to filter node and run exec cmd
  4. host-alias: set host-alias for hosts via specified Clusterfile
    • [P1]host-alias hostnames
    • [P1]host-alias ip
  5. manifest: manipulate manifest lists
    • [P2]Add images to a manifest list
    • [P2]Create manifest list
    • [P2]Delete manifest list
    • [P2]Display the contents of a manifest list
    • [P2]Push a manifest list to a registry
    • [P2]Remove an entry from a manifest list
  6. search: search Sealer Image in default registry
    • [P2]search Sealer Image in default registry

config:

  • [P1]If the configured path does not exist, write data directly to the file
  • [P1]If the toSecret processor is configured, the data is converted into k8s secret
  • [P1]If the Strategy field of the config configuration is Merge, the files specified by data and path are merged

registry:

  • [P1]Configure registry cert
  • [P1]Configure registry basic auth
  • [P2]Configure container runtime registry address

Compatibility:

  • [P2]Supported Architectures: amd64 and arm64
@zhy76 zhy76 added the kind/feature Category issues or PRs related to feature request label Jan 10, 2023
@zhy76
Copy link
Member Author

zhy76 commented Feb 7, 2023

E2E test document

Sealer E2E test is inspired by kind, uses a container to emulate a node by running systemd inside the container and hosting other processes with systemd.

Principle of sealer k8s in docker

Sealer uses(sealer/pkg/infra/container/imagecontext/base/Dockerfile)to build a basic image: sealerio/sealer-base-image:v1,and use this image to start the container to emulate node。

After starting the container, the sealer binary is transferred to the container through ssh, and the sealer commands such as: sealer run and sealer apply are invoked through ssh to create the k8s cluster (k8s in docker), as shown in the figure below:

sealer E2E drawio (1)

How to run E2E test locally

The code in test repository is a set of Ginkgo and Gomega based integration tests that execute commands using the sealer CLI.

Prerequisites

Before you run the tests, you'll need a sealer binary in your machine executable path and install docker.

Run the Tests

To run a single test or set of tests, you'll need the Ginkgo tool installed on your machine:

go install github.com/onsi/ginkgo/[email protected]

To install Sealer and prepare the test environment:

#build sealer source code to binary for local e2e-test in containers
git clone https://github.com/sealerio/sealer.git
cd sealer/ && make build-in-docker
cp _output/bin/sealer/linux_amd64/sealer /usr/local/bin

#prepare test environment
export REGISTRY_URL={your registry}
export REGISTRY_USERNAME={user name}
export REGISTRY_PASSWORD={password}
#default test image name: docker.io/sealerio/kubernetes:v1-22-15-sealerio-2
export IMAGE_NAME={test image name}

To execute the entire test suite:

cd sealer && ginkgo test

You can then use the -focus option to run subsets of the test suite:

ginkgo --focus="sealer login" test

You can then use the v option to print out default reporter as all specs begin:

ginkgo -v test

More ginkgo helpful info see:

ginkgo --help

How to run E2E Tests using github action

Before we run the CI by using github aciton, please make sure that these four variables: REGISTRY_URL={your registry}, REGISTRY_USERNAME={user name}, REGISTRY_PASSWORD={password}, IMAGE_NAME={test image name} have been setted in github's secret (for sealer login and sealer image tests).

CI is triggered when we push a branch with name starts with release or comment /test all in PR,you can also comment /test {test to run} in PR to run subsets of the test suite.

How to write E2E test cases for sealer

E2E tests required by sealer can be divided into those that need cluster construction and those that do not. For tests that need cluster construction, container needs to be started to simulate node (such as sealer run and sealer apply). If you don't need to build a cluster, you just need to execute it on the machine (e.g., sealer pull, sealer tag, sealer build).

E2E test entry

Sealer all E2E test files are in the test directory, where e2e_test.go is the entry to E2E test.

The function: func TestSealerTests(t *testing.T)is the entry point for Ginkgo - the go test runner will run this function when you run go testor ginkgo.RegisterFailHandler(Fail)is the single line of glue code connecting Ginkgo to Gomega. If we were to avoid dot-imports this would read as gomega.RegisterFailHandler(ginkgo.Fail)- what we're doing here is telling our matcher library (Gomega) which function to call (Ginkgo's Fail) in the event a failure is detected.

Writing Specs

You can use ginkgo generate to generate a E2E test file (eg. ginkgo generate sealer_alpha)

Ginkgo allows you to hierarchically organize the specs in your suite using container nodes. Ginkgo provides three synonymous nouns for creating container nodes: DescribeContext, and When. These three are functionally identical and are provided to help the spec narrative flow. You usually Describedifferent capabilities of your code and explore the behavior of each capability across different Contexts.

For example:

var _ = Describe("sealer login", func() {
	Context("login docker registry", func() {
		AfterEach(func() {
			registry.Logout()
		})
		It("with correct name and password", func() {
			image.CheckLoginResult(
				settings.RegistryURL,
				settings.RegistryUsername,
				settings.RegistryPasswd,
				true)
		})
		It("with incorrect name and password", func() {
			image.CheckLoginResult(
				settings.RegistryURL,
				settings.RegistryPasswd,
				settings.RegistryUsername,
				false)
		})
		It("with only name", func() {
			image.CheckLoginResult(
				settings.RegistryURL,
				settings.RegistryUsername,
				"",
				false)
		})
		It("with only password", func() {
			image.CheckLoginResult(
				settings.RegistryURL,
				"",
				settings.RegistryPasswd,
				false)
		})
		It("with only registryURL", func() {
			image.CheckLoginResult(
				settings.RegistryURL,
				"",
				"",
				false)
		})
	})
})

The configuration of e2e test is in test/testhelper/settings, The test data and methods for e2e test are here:test/suites.

More information about ginkgo and gomega can be found in the documentation:Ginkgo and Gomega.

Configure github action file

The github action file for e2e test is under the .github/workflows directory. You need to configure the file here for CI.

For example:

name: {Test name}

on:
  push:
    branches: "release*"
  issue_comment:
    types:
      - created
      
permissions:
  statuses: write

jobs:
  build:
    name: test
    runs-on: ubuntu-latest
    if: ${{ (github.event.issue.pull_request && (github.event.comment.body == '/test all' || github.event.comment.body == '/test {name}')) || github.event_name == 'push' }}
    env:
      GO111MODULE: on
    steps:
      - name: Get PR details
        if: ${{ github.event_name == 'issue_comment'}}
        uses: xt0rted/pull-request-comment-branch@v1
        id: comment-branch

      - name: Set commit status as pending
        if: ${{ github.event_name == 'issue_comment'}}
        uses: myrotvorets/set-commit-status-action@master
        with:
          sha: ${{ steps.comment-branch.outputs.head_sha }}
          token: ${{ secrets.GITHUB_TOKEN }}
          status: pending

      - name: Github API Request
        id: request
        uses: octokit/[email protected]
        with:
          route: ${{ github.event.issue.pull_request.url }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Get PR informations
        id: pr_data
        run: |
          echo "repo_name=${{ fromJson(steps.request.outputs.data).head.repo.full_name }}" >> $GITHUB_STATE
          echo "repo_clone_url=${{ fromJson(steps.request.outputs.data).head.repo.clone_url }}" >> $GITHUB_STATE
          echo "repo_ssh_url=${{ fromJson(steps.request.outputs.data).head.repo.ssh_url }}" >> $GITHUB_STATE
      - name: Check out code into the Go module directory
        uses: actions/checkout@v3
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          repository: ${{fromJson(steps.request.outputs.data).head.repo.full_name}}
          ref: ${{fromJson(steps.request.outputs.data).head.ref}}
          path: src/github.com/sealerio/sealer
      - name: Install deps
        run: |
          sudo su
          sudo apt-get update
          sudo apt-get install -y libgpgme-dev libbtrfs-dev libdevmapper-dev
          sudo mkdir /var/lib/sealer
      - name: Set up Go 1.17
        uses: actions/setup-go@v3
        with:
          go-version: 1.17
        id: go

      - name: Install sealer and ginkgo
        shell: bash
        run: |
          docker run --rm -v ${PWD}:/usr/src/sealer -w /usr/src/sealer registry.cn-qingdao.aliyuncs.com/sealer-io/sealer-build:v1 make linux
          export SEALER_DIR=${PWD}/_output/bin/sealer/linux_amd64
          echo "$SEALER_DIR" >> $GITHUB_PATH
          go install github.com/onsi/ginkgo/[email protected]
          go install github.com/onsi/gomega/[email protected]
          GOPATH=`go env GOPATH`
          echo "$GOPATH/bin" >> $GITHUB_PATH
        working-directory: src/github.com/sealerio/sealer

      - name: Run **{Test name}** test
        shell: bash
        working-directory: src/github.com/sealerio/sealer
        env:
          REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
          REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
          REGISTRY_URL: ${{ secrets.REGISTRY_URL }}
          IMAGE_NAME: ${{ secrets.IMAGE_NAME}}
          ACCESSKEYID: ${{ secrets.ACCESSKEYID }}
          ACCESSKEYSECRET: ${{ secrets.ACCESSKEYSECRET }}
          RegionID: ${{ secrets.RegionID }}
        run: | # Your main focus is here
          ginkgo -v --focus="sealer {test name}" test

      - name: Set final commit status
        uses: myrotvorets/set-commit-status-action@master
        if: always()
        with:
          sha: ${{ steps.comment-branch.outputs.head_sha }}
          token: ${{ secrets.GITHUB_TOKEN }}
          status: ${{ job.status }}

More information about github action can be found in the documentation:Github action.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature Category issues or PRs related to feature request
Projects
None yet
Development

No branches or pull requests

1 participant