Add E2E tests (#15)

diff --git a/.github/file-filters.yaml b/.github/file-filters.yaml
new file mode 100644
index 0000000..db6526c
--- /dev/null
+++ b/.github/file-filters.yaml
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+src:
+  - '**/*.go'
+  - 'go.mod'
+  - '.golangci.yml'
+  - '.github/*.yml'
+  - '.github/*.yaml'
+  - 'assets/*.yaml'
+  - 'assets/*.yml'
+  - 'deployments/*.yaml'
+  - 'deployments/*.yml'
+  - 'scripts/*.sh'
diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml
index ac62b95..913352f 100644
--- a/.github/workflows/build-and-test.yaml
+++ b/.github/workflows/build-and-test.yaml
@@ -21,14 +21,22 @@
 on:
   pull_request:
 
+concurrency:
+  group: sw-k8s-event-exporter-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
 jobs:
   build-and-test:
     name: Build and Test
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
+
+      - name: Check for non-document changes
+        uses: getsentry/paths-filter@v2
+        id: changes
         with:
-          submodules: true
+          filters: .github/file-filters.yaml
 
       - uses: actions/setup-go@v2
         with:
@@ -39,14 +47,25 @@
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
-      - name: Test
+      - name: Lint
+        if: steps.changes.outputs.src == 'true'
+        run: make lint
+
+      - name: Unit tests
+        if: steps.changes.outputs.src == 'true'
         run: make test
 
       - name: Build
-        run: make
+        run: make build
 
       - name: Build Docker Image
-        run: make -C build/package/docker
+        run: VERSION=test HUB=apache make -C build/package/docker
+
+      - name: E2E tests
+        if: steps.changes.outputs.src == 'true'
+        uses: apache/skywalking-infra-e2e@main
+        with:
+          e2e-file: $GITHUB_WORKSPACE/test/e2e/e2e.yaml
 
   gateway:
     name: Gateway
diff --git a/Makefile b/Makefile
index 73aa083..76859ce 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,11 @@
 
 include scripts/base.mk
 
+E2E_CLI_VERSION=${E2E_CLI_VERSION:-'2a33478'}
+
+# Whether to skip docker build in E2E tests
+E2E_SKIP_BUILD ?= 0
+
 all: clean lint test build
 
 .PHONY: lint
@@ -88,3 +93,15 @@
 	shasum -a 512 $(RELEASE_SRC).tgz > $(RELEASE_SRC).tgz.sha512
 	gpg --batch --yes --armor --detach-sig $(RELEASE_BIN).tgz
 	shasum -a 512 $(RELEASE_BIN).tgz > $(RELEASE_BIN).tgz.sha512
+
+### Run E2E tests locally.
+.PHONY: e2e
+e2e: check-e2e-cli
+	ifeq ($(E2E_SKIP_BUILD), 0)
+		VERSION=test HUB=apache make -C build/package/docker build
+	endif
+	e2e run -c test/e2e/e2e.yaml
+
+.PHONY: check-e2e-cli
+check-e2e-cli:
+	e2e -h || go install github.com/apache/skywalking-infra-e2e/cmd/e2e@$(E2E_CLI_VERSION)
diff --git a/assets/default-config.yaml b/assets/default-config.yaml
index d3bd1f6..35ad499 100644
--- a/assets/default-config.yaml
+++ b/assets/default-config.yaml
@@ -17,13 +17,14 @@
 #
 
 filters:
+  # Note: for the following filters that support regular expression, please use "^<string>$" to exact match.
   - reason: ""     # filter events of the specified reason, regular expression like "Killing|Killed" is supported.
     message: ""    # filter events of the specified message, regular expression like "Pulling container.*" is supported.
     minCount: 1    # filter events whose count is >= the specified value.
     type: ""       # filter events of the specified type, regular expression like "Normal|Error" is supported.
     action: ""     # filter events of the specified action, regular expression is supported.
     kind: "Pod|Service"       # filter events of the specified kind, regular expression like "Pod|Service" is supported.
-    namespace: "default"  # filter events from the specified namespace, regular expression like "default|bookinfo" is supported, empty means all namespaces.
+    namespace: "^default$"  # filter events from the specified namespace, regular expression like "default|bookinfo" is supported, empty means all namespaces.
     name: ""       # filter events of the specified involved object name, regular expression like ".*bookinfo.*" is supported.
     service: "[^\\s]{1,}"  # filter events belonging to services whose name is not empty.
     exporters:     # events satisfy this filter can be exported into several exporters that are defined in the `exporters` section below.
diff --git a/deployments/base/deployment.yaml b/deployments/base/deployment.yaml
index fab2b61..c8cf5f6 100644
--- a/deployments/base/deployment.yaml
+++ b/deployments/base/deployment.yaml
@@ -34,7 +34,7 @@
       containers:
         - name: skywalking-event-exporter
           image: skywalking-event-exporter
-          imagePullPolicy: Always
+          imagePullPolicy: IfNotPresent
           args:
             - start
             - -v=debug
diff --git a/deployments/test/config/config.yaml b/deployments/test/config/config.yaml
new file mode 100644
index 0000000..5cb09e0
--- /dev/null
+++ b/deployments/test/config/config.yaml
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+filters:
+  - namespace: ^e2e-test$
+    exporters:
+      - skywalking
+
+exporters:
+  skywalking:
+    template:
+      source:
+        service: "{{ .Service.Name }}"
+        serviceInstance: "{{ .Pod.Name }}"
+        endpoint: ""
+      message: "{{ .Event.Message }}"
+    address: "skywalking-oap.skywalking:11800"
+    enableTLS: false
+    insecureSkipVerify: true
+    trustedCertPath: "/certs/ca.crt"
+    clientCertPath: "/certs/tls.crt"
+    clientKeyPath: "/certs/tls.key"
diff --git a/deployments/test/kustomization.yaml b/deployments/test/kustomization.yaml
new file mode 100644
index 0000000..ca25a2d
--- /dev/null
+++ b/deployments/test/kustomization.yaml
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+  - ../base
+  - ./namespace.yaml
+
+namespace: e2e-test
+
+configMapGenerator:
+  - files:
+      - config.yaml=config/config.yaml
+    name: skywalking-event-exporter-cm
+
+generatorOptions:
+  disableNameSuffixHash: true
+images:
+  - name: skywalking-event-exporter
+    newName: apache/skywalking-kubernetes-event-exporter
+    newTag: test
diff --git a/deployments/test/namespace.yaml b/deployments/test/namespace.yaml
new file mode 100644
index 0000000..c33d14a
--- /dev/null
+++ b/deployments/test/namespace.yaml
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: e2e-test
diff --git a/scripts/prepare-e2e.sh b/scripts/prepare-e2e.sh
new file mode 100755
index 0000000..bba8e7d
--- /dev/null
+++ b/scripts/prepare-e2e.sh
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+OS=$(go env GOOS)
+ARCH=$(go env GOHOSTARCH)
+
+# prepare base dir
+TMP_DIR=/tmp/sw-event-exporter-e2e
+BIN_DIR=$TMP_DIR/bin
+mkdir -p $TMP_DIR $BIN_DIR && cd $TMP_DIR
+
+KUBECTL_VERSION=${KUBECTL_VERSION:-'v1.19.1'}
+SWCTL_VERSION=${SWCTL_VERSION:-'0.10.0'}
+HELM_VERSION=${HELM_VERSION:-'helm-v3.0.0'}
+
+prepare_ok=true
+
+function error_check() {
+    if [ $? -ne 0 ]; then
+        echo "[ERROR] Failed to install $1, please check"
+        prepare_ok=false
+    fi
+}
+
+function install_kubectl()
+{
+    if ! command -v kubectl &> /dev/null; then
+      echo "Installing kubectl"
+      mkdir -p $TMP_DIR/kubectl && cd $TMP_DIR/kubectl
+      curl -LO https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/${OS}/${ARCH}/kubectl && chmod +x ./kubectl && mv ./kubectl ${BIN_DIR}
+      error_check "kubectl"
+    fi
+}
+
+function install_swctl()
+{
+    if ! command -v swctl &> /dev/null; then
+      echo "Installing swctl"
+      mkdir -p $TMP_DIR/swctl && cd $TMP_DIR/swctl
+      curl -kLo skywalking-cli.tar.gz https://github.com/apache/skywalking-cli/archive/${SWCTL_VERSION}.tar.gz
+      tar -zxf skywalking-cli.tar.gz --strip=1
+      VERSION=${SWCTL_VERSION} make install DESTDIR=${BIN_DIR}
+      error_check "swctl"
+    fi
+}
+
+function install_yq()
+{
+    if ! command -v yq &> /dev/null; then
+      echo "Installing yq"
+      mkdir -p $TMP_DIR/yq && cd $TMP_DIR/yq
+      wget https://github.com/mikefarah/yq/releases/download/v4.11.1/yq_${OS}_${ARCH}.tar.gz -O - |\
+      tar xz && mv yq_${OS}_${ARCH} ${BIN_DIR}/yq
+      error_check "yq"
+    fi
+}
+
+function install_helm() {
+  if ! command -v helm &> /dev/null; then
+    echo "Installing helm"
+    mkdir -p $TMP_DIR/helm && cd $TMP_DIR/helm
+    curl -sSL https://get.helm.sh/${HELM_VERSION}-${OS}-${ARCH}.tar.gz | tar xz -C $BIN_DIR --strip-components=1 ${OS}-${ARCH}/helm
+    mv ${OS}-${ARCH}/helm ${BIN_DIR}/helm
+    error_check "helm"
+  fi
+}
+
+function install_all()
+{
+    install_kubectl
+    install_swctl
+    install_yq
+    install_helm
+
+    if [ "$prepare_ok" = false ]; then
+        echo "Install e2e dependencies failed"
+        exit 1
+    else
+        echo "Install e2e dependencies successfully"
+        exit 0
+    fi
+}
+
+install_all
diff --git a/test/e2e/e2e.yaml b/test/e2e/e2e.yaml
new file mode 100644
index 0000000..fdcf01c
--- /dev/null
+++ b/test/e2e/e2e.yaml
@@ -0,0 +1,66 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+setup:
+  env: kind
+  file: ./kind.yaml
+  init-system-environment: ./env
+  kind:
+    import-images:
+      - apache/skywalking-kubernetes-event-exporter:test
+    expose-ports:
+      - namespace: skywalking
+        resource: service/skywalking-oap
+        port: 12800
+  steps:
+    - name: Set PATH
+      command: export PATH=/tmp/sw-event-exporter-e2e/bin:$PATH
+    - name: Install tools
+      command: bash scripts/prepare-e2e.sh
+    - name: Deploy SkyWalking OAP and UI
+      command: |
+        helm repo add skywalking https://apache.jfrog.io/artifactory/skywalking-helm
+        helm install --create-namespace skywalking skywalking/skywalking -n skywalking \
+          --set oap.replicas=1 \
+          --set oap.storageType=h2 \
+          --set oap.image.tag=$OAP_IMAGE_TAG \
+          --set ui.image.tag=$UI_IMAGE_TAG \
+          --set elasticsearch.enabled=false \
+          --set oap.env.JAVA_OPTS='-Dmode='
+      wait:
+        - namespace: skywalking
+          resource: pod
+          for: condition=Ready
+    - name: Deploy k8s event exporter
+      command: kubectl apply -k deployments/test
+      wait:
+        - namespace: e2e-test
+          resource: pod
+          for: condition=Ready
+    - name: Trigger k8s events
+      command: kubectl -n e2e-test run test --image=apache/skywalking:not-exist
+      wait:
+        - namespace: e2e-test
+          resource: pod
+          for: condition=PodScheduled
+  timeout: 10m
+
+verify:
+  retry:
+    count: 20
+    interval: 10s
+  cases:
+    - query: swctl --display yaml --base-url=http://${service_skywalking_oap_host}:${service_skywalking_oap_12800}/graphql event ls --type Error
+      expected: expected/events.yaml
diff --git a/test/e2e/env b/test/e2e/env
new file mode 100644
index 0000000..e569006
--- /dev/null
+++ b/test/e2e/env
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+OAP_IMAGE_TAG=9.0.0
+UI_IMAGE_TAG=9.0.0
diff --git a/test/e2e/expected/events.yaml b/test/e2e/expected/events.yaml
new file mode 100644
index 0000000..cc72811
--- /dev/null
+++ b/test/e2e/expected/events.yaml
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+events:
+  {{- contains .events }}
+  - uuid: {{ notEmpty .uuid }}
+    source:
+      service: ""
+      serviceinstance: ""
+      endpoint: ""
+    name: Failed
+    type: Error
+    message: "Error: ImagePullBackOff"
+    parameters: []
+    starttime: {{ gt .starttime 0 }}
+    endtime: {{ gt .endtime 0 }}
+  - uuid: {{ notEmpty .uuid }}
+    source:
+      service: ""
+      serviceinstance: ""
+      endpoint: ""
+    name: Failed
+    type: Error
+    message: "Error: ErrImagePull"
+    parameters: []
+    starttime: {{ gt .starttime 0 }}
+    endtime: {{ gt .endtime 0 }}
+  {{- end }}
+total: {{ ge .total 2 }}
diff --git a/test/e2e/kind.yaml b/test/e2e/kind.yaml
new file mode 100644
index 0000000..a04057c
--- /dev/null
+++ b/test/e2e/kind.yaml
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+kind: Cluster
+apiVersion: kind.x-k8s.io/v1alpha4
+nodes:
+  - role: control-plane
+  - role: worker
+  - role: worker