Skip to content

Commit

Permalink
Modify CI Test to Fetch kubebuilder Release Binary
Browse files Browse the repository at this point in the history
This commit modifies CI test to fetch kubebuilder release binary
before test runs.
This enables to run go test using envtest package from
kubernetes-sig/controller-runtime.
  • Loading branch information
vanou committed Jul 18, 2020
1 parent 7408725 commit e1ec091
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 36 deletions.
126 changes: 126 additions & 0 deletions hack/ci/fetch_kubebuilder_release_bin.sh
@@ -0,0 +1,126 @@
#!/bin/bash

# Copyright 2020 The Kubernetes Authors.
#
# Licensed 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.


# This shell fetches kubebuilder release binary and puts it under
# /tmp/kubebuilder_bin/kubebuilder/bin/
# Then sets KUBEBUILDER_ASSETS to that path to make go test using
# envtest package in kubernetes-sigs/controller-runtime work properly.
#
# This script is largely based on CI script file "chek-everything.sh"
# of kubernetes-sigs/controller-runtime

# Version of kubebuilder release binary which this script attempts to fetch
kubebuilder_release_version="2.3.1"

goos=$(go env GOHOSTOS)
goarch=$(go env GOHOSTARCH)

# Supported arch under above release version
# See source code of standard library "build" ("go/build") for os&arch constant
os_darwin='darwin'
darwin_supported_arch=('amd64')

# Supported arch under above release version
# See source code of standard library "build" ("go/build") for os&arch constant
os_linux='linux'
linux_supported_arch=('amd64' 'arm64' 'ppc64le')

kubebuilder_release_base_url='https://github.com/kubernetes-sigs/kubebuilder/releases/download'
fetch_url_base="${kubebuilder_release_base_url}/v${kubebuilder_release_version}"


# Fetch kubebuilder release binaries and place them under "<argument>/kubebuilder/bin/"
function fetch_kb_bin () {
local dest_dir="${1}/kubebuilder"
local archive_file
local checksum_file="checksums.txt"
local found

# Check whether kubebuilder release binary is provided for current environment's OS & Arch
if [[ ${goos} == ${os_darwin} ]]; then
for (( i=0; i < ${#darwin_supported_arch[@]}; i++ )); do
if [[ ${goarch} == ${darwin_supported_arch[${i}]} ]]; then
found="true"
break
fi
done

if [[ -z ${found} ]]; then
echo "No kubebuilder supported arch under ${goos}: ${goarch}"
exit 1
fi

elif [[ ${goos} == ${os_linux} ]]; then
for (( i=0; i < ${#linux_supported_arch[@]}; i++ )); do
if [[ ${goarch} == ${linux_supported_arch[${i}]} ]]; then
found="true"
break
fi
done

if [[ -z ${found} ]]; then
echo "No kubebuilder supported arch under ${goos}: ${goarch}"
exit 1
fi

else
echo "Not kubebuilder supported os: ${goos}"
exit 1
fi

archive_file="kubebuilder_${kubebuilder_release_version}_${goos}_${goarch}.tar.gz"

mkdir -p ${dest_dir}

# Fetch kubebuilder release binary
curl -fsL "${fetch_url_base}/${archive_file}" -o "/tmp/${archive_file}"
if [[ ${?} != 0 ]]; then
echo "Failed to curl kubebuilder release binary"
exit 1
fi

# Fetch checksum file
curl -fsL "${fetch_url_base}/${checksum_file}" -o "/tmp/${checksum_file}"
if [[ ${?} != 0 ]]; then
echo "Failed to curl checksum file"
exit 1
fi

# Hash & check fetched binary
(
cd /tmp
sha256sum -c --quiet --ignore-missing "/tmp/${checksum_file}"
if [[ ${?} != 0 ]]; then
echo "Maybe, kubebuilder release binary got broken & doesn't match hash value in ${checksum_file}"
exit 1
fi
)

# Unpack
tar -C ${dest_dir} -xzf "/tmp/${archive_file}" --strip-components=1

# Check expected binaries exist
if [[ !(-x ${dest_dir}/bin/etcd && -x ${dest_dir}/bin/kubectl && -x ${dest_dir}/bin/kube-apiserver) ]]; then
echo "There are no expected binaries at ${dset_dir}/bin : etcd, kubectl & kube-apiserver"
exit 1
fi

# Set KUBEBUILDER_ASSETS environment variable
export KUBEBUILDER_ASSETS="${dest_dir}/bin"
}

fetch_kb_bin "/tmp"
4 changes: 4 additions & 0 deletions hack/ci/test.sh
Expand Up @@ -18,7 +18,11 @@ set -o errexit
set -o nounset
set -o pipefail

CI_ROOT=$(dirname "${BASH_SOURCE}")
REPO_ROOT=$(dirname "${BASH_SOURCE}")/../..

source "${CI_ROOT}/fetch_kubebuilder_release_bin.sh"

cd "${REPO_ROOT}"

export GO111MODULE=on
Expand Down
8 changes: 4 additions & 4 deletions hack/smoketest.go
Expand Up @@ -283,22 +283,22 @@ func verifyOrTimeout(operators []AddonTest, duration time.Duration, desc string,
}

func verifyExistRole(clientset kubernetes.Interface, namespace string, role string) error {
if _, err := clientset.RbacV1().Roles(namespace).Get(context.TODO(),role, metav1.GetOptions{}); err != nil {
if _, err := clientset.RbacV1().Roles(namespace).Get(context.TODO(), role, metav1.GetOptions{}); err != nil {
return err
}
return nil
}

func verifyExistClusterRole(clientset kubernetes.Interface, name string) error {
if _, err := clientset.RbacV1().ClusterRoles().Get(context.TODO(),name, metav1.GetOptions{}); err != nil {
if _, err := clientset.RbacV1().ClusterRoles().Get(context.TODO(), name, metav1.GetOptions{}); err != nil {
return err
}

return nil
}

func verifyExistClusterRoleBinding(clientset kubernetes.Interface, name string) error {
if _, err := clientset.RbacV1().ClusterRoleBindings().Get(context.TODO(),name, metav1.GetOptions{}); err != nil {
if _, err := clientset.RbacV1().ClusterRoleBindings().Get(context.TODO(), name, metav1.GetOptions{}); err != nil {
return err
}

Expand All @@ -317,7 +317,7 @@ func verifySteps(clientset kubernetes.Interface, steps []verifyStep) error {
type PodSet []corev1.Pod

func Pods(h TestHarness, namespace string) PodSet {
pods, err := h.Clientset().CoreV1().Pods(namespace).List(context.TODO(),metav1.ListOptions{})
pods, err := h.Clientset().CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
h.Fatalf("error listing pods: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/patterns/addon/pkg/loaders/http.go
Expand Up @@ -64,7 +64,7 @@ func (r *HTTPRepository) LoadChannel(ctx context.Context, name string) (*Channel
return channel, nil
}

func (r *HTTPRepository) LoadManifest(ctx context.Context, packageName string, id string) (map[string] string, error) {
func (r *HTTPRepository) LoadManifest(ctx context.Context, packageName string, id string) (map[string]string, error) {
if !allowedManifestId(packageName) {
return nil, fmt.Errorf("invalid package name: %q", id)
}
Expand All @@ -81,7 +81,7 @@ func (r *HTTPRepository) LoadManifest(ctx context.Context, packageName string, i
if err != nil {
return nil, fmt.Errorf("error reading package %s: %v", p, err)
}
result := map[string]string {
result := map[string]string{
p: string(b),
}
return result, nil
Expand Down
6 changes: 3 additions & 3 deletions pkg/patterns/declarative/pkg/applier/direct.go
Expand Up @@ -2,14 +2,15 @@ package applier

import (
"context"
"os"
"strings"

"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/kubectl/pkg/cmd/apply"
cmdDelete "k8s.io/kubectl/pkg/cmd/delete"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"os"
"strings"
)

type DirectApplier struct {
Expand Down Expand Up @@ -55,4 +56,3 @@ func (d *DirectApplier) Apply(ctx context.Context,

return applyOpts.Run()
}

1 change: 0 additions & 1 deletion pkg/patterns/declarative/pkg/applier/exec.go
Expand Up @@ -88,4 +88,3 @@ func (c *ExecKubectl) Apply(ctx context.Context, namespace string, manifest stri

return nil
}

32 changes: 15 additions & 17 deletions pkg/patterns/declarative/pkg/manifest/objects_test.go
Expand Up @@ -2,16 +2,17 @@ package manifest

import (
"context"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"testing"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

func Test_Object(t *testing.T) {
tests := []struct{
name string
inputManifest string
tests := []struct {
name string
inputManifest string
expectedObject []*Object
expectedBlobs []string
expectedBlobs []string
}{
{
name: "simple applied manifest",
Expand All @@ -21,14 +22,14 @@ kind: ServiceAccount
metadata:
name: foo-operator
namespace: kube-system`,
expectedObject: []*Object{
expectedObject: []*Object{
{
object: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": "foo-operator",
"name": "foo-operator",
"namespace": "kube-system",
},
},
Expand All @@ -49,8 +50,8 @@ configMapGenerator:
files:
- Corefile`,
expectedObject: []*Object{},
expectedBlobs:[]string{
`resources:
expectedBlobs: []string{
`resources:
- services.yaml
- deployment.yaml
configMapGenerator:
Expand Down Expand Up @@ -83,17 +84,17 @@ configMapGenerator:
object: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ServiceAccount",
"kind": "ServiceAccount",
"metadata": map[string]interface{}{
"name": "foo-operator",
"name": "foo-operator",
"namespace": "kube-system",
},
},
},
},
},
expectedBlobs:[]string{
`resources:
expectedBlobs: []string{
`resources:
- services.yaml
- deployment.yaml
configMapGenerator:
Expand Down Expand Up @@ -150,6 +151,3 @@ configMapGenerator:
})
}
}



6 changes: 3 additions & 3 deletions pkg/test/mocks/cache.go
Expand Up @@ -21,11 +21,11 @@ func (FakeCache) List(ctx context.Context, list runtime.Object, opts ...client.L
panic("implement me")
}

func (FakeCache) GetInformer(ctx context.Context,obj runtime.Object) (toolscache.Informer, error) {
func (FakeCache) GetInformer(ctx context.Context, obj runtime.Object) (toolscache.Informer, error) {
panic("implement me")
}

func (FakeCache) GetInformerForKind(gctx context.Context,vk schema.GroupVersionKind) (toolscache.Informer, error) {
func (FakeCache) GetInformerForKind(gctx context.Context, vk schema.GroupVersionKind) (toolscache.Informer, error) {
panic("implement me")
}

Expand All @@ -37,6 +37,6 @@ func (FakeCache) WaitForCacheSync(stop <-chan struct{}) bool {
panic("implement me")
}

func (FakeCache) IndexField(ctx context.Context,obj runtime.Object, field string, extractValue client.IndexerFunc) error {
func (FakeCache) IndexField(ctx context.Context, obj runtime.Object, field string, extractValue client.IndexerFunc) error {
panic("implement me")
}
5 changes: 3 additions & 2 deletions pkg/test/mocks/manager.go
Expand Up @@ -17,11 +17,12 @@ limitations under the License.
package mocks

import (
"net/http"

"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/record"
"net/http"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
Expand Down Expand Up @@ -120,4 +121,4 @@ func (Manager) AddMetricsExtraHandler(path string, handler http.Handler) error {

func (Manager) Elected() <-chan struct{} {
panic("implement me")
}
}
9 changes: 5 additions & 4 deletions utils/utils.go
Expand Up @@ -2,15 +2,17 @@ package utils

import (
"context"
"github.com/pkg/errors"
"strings"

"github.com/pkg/errors"

"net"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"k8s.io/klog"
"net"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
Expand All @@ -29,7 +31,6 @@ func getCoreDNSService(ctx context.Context, c client.Client) (*corev1.Service, e
return kubernetesService, err
}


// FindDNSClusterIP tries to find the Cluster IP to be used by the DNS service
// It is usually the 10th address to the Kubernetes Service Cluster IP
// If the Kubernetes Service Cluster IP is not found, we default it to be "10.96.0.10"
Expand Down

0 comments on commit e1ec091

Please sign in to comment.