Skip to content

Commit

Permalink
6584 staging (stolostron#9)
Browse files Browse the repository at this point in the history
* Code and unit tests (stolostron#7)

* Add packages for interacting with the OCM and redhat auth apis

* Change controller to use the api packages. Add unit tests for covering basic controller functionality with mocks

* Add make targets to easily modify the deployment to target the mock server

* Add endpoint to mock auth api. Change port to 3000 so it doesn't conflict with metrics server.

* Remove unused packages

* 6584 functiontest (stolostron#8)

* Add packages for interacting with the OCM and redhat auth apis

* Change controller to use the api packages. Add unit tests for covering basic controller functionality with mocks

* Add make targets to easily modify the deployment to target the mock server

* Add endpoint to mock auth api. Change port to 3000 so it doesn't conflict with metrics server.

* Remove unused packages

* Add functional tests, add support to mock server for checking for search filter

* Update makefile for integration test

* Increase test coverage

* Containerize functional tests

* Build test image in travis

* update travis
  • Loading branch information
JakobGray authored Nov 17, 2020
1 parent 335852e commit 8022d40
Show file tree
Hide file tree
Showing 41 changed files with 3,287 additions and 349 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@ build-harness-extensions
# override build harness vendoring
!vbh/.build-harness-vendorized
!vbh/build-harness
!vbh/build-harness-extensions
!vbh/build-harness-extensions

# Functional test results
integration_tests/results
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ env:
# Required
- OS=linux
- COMPONENT_TAG_EXTENSION="-${TRAVIS_COMMIT}"
- COMPONENT_NAME=discovery-operator

# Component Specific
- COMPONENT_INIT_COMMAND=${TRAVIS_BUILD_DIR}/cicd-scripts/install-dependencies.sh
Expand All @@ -48,6 +49,9 @@ jobs:
make component/build
make component/push
make security/scans
COMPONENT_NAME=discovery-operator-tests COMPONENT_BUILD_COMMAND=${TRAVIS_BUILD_DIR}/cicd-scripts/build-test-image.sh
make component/build
make component/push
- stage: unit-test
name: "Run unit tests"
script:
Expand Down Expand Up @@ -82,3 +86,7 @@ jobs:
- |
make
make pipeline-manifest/update PIPELINE_MANIFEST_COMPONENT_SHA256=${TRAVIS_COMMIT} PIPELINE_MANIFEST_COMPONENT_REPO=${TRAVIS_REPO_SLUG} PIPELINE_MANIFEST_BRANCH=${TRAVIS_BRANCH}
rm -rf pipeline
echo "Waiting 60s before publishing test image..." && sleep 60
COMPONENT_NAME=discovery-operator-tests
make pipeline-manifest/update PIPELINE_MANIFEST_COMPONENT_SHA256=${TRAVIS_COMMIT} PIPELINE_MANIFEST_COMPONENT_REPO=${TRAVIS_REPO_SLUG} PIPELINE_MANIFEST_BRANCH=${TRAVIS_BRANCH}
16 changes: 14 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ GOBIN=$(shell go env GOBIN)
endif

-include testserver/Makefile
-include integration_tests/Makefile

all: manager

Expand All @@ -53,7 +54,12 @@ ENVTEST_ASSETS_DIR = $(shell pwd)/testbin
test: generate fmt vet manifests
mkdir -p $(ENVTEST_ASSETS_DIR)
test -f $(ENVTEST_ASSETS_DIR)/setup-envtest.sh || curl -sSLo $(ENVTEST_ASSETS_DIR)/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.6.3/hack/setup-envtest.sh
source $(ENVTEST_ASSETS_DIR)/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out
source $(ENVTEST_ASSETS_DIR)/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test `go list ./... | grep -v integration_tests` -coverprofile cover.out

# Run tests
integration-tests: install deploy server/deploy setenv
kubectl wait --for=condition=available --timeout=60s deployment/discovery-controller -n open-cluster-management
ginkgo -tags functional -v integration_tests/controller_tests

# Build manager binary
manager: generate fmt vet
Expand Down Expand Up @@ -162,4 +168,10 @@ samples:
$(KUSTOMIZE) build config/samples | kubectl apply -f -

logs:
@oc logs -f $(shell oc get pod -l app=discovery-controller -o jsonpath="{.items[0].metadata.name}")
@oc logs -f $(shell oc get pod -l app=discovery-controller -o jsonpath="{.items[0].metadata.name}")

setenv:
kubectl set env deployment/discovery-controller OCM_URL="http://mock-ocm-server.open-cluster-management.svc.cluster.local:3000"

unsetenv:
kubectl set env deployment/discovery-controller OCM_URL-
6 changes: 6 additions & 0 deletions cicd-scripts/build-test-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
# Copyright (c) 2020 Red Hat, Inc.

echo "Building test-image"

docker build . -f integration_tests/build/Dockerfile -t $1
136 changes: 81 additions & 55 deletions controllers/discoveredclusterrefresh_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"

discoveryv1 "github.com/open-cluster-management/discovery/api/v1"
"github.com/open-cluster-management/discovery/pkg/auth"
"github.com/open-cluster-management/discovery/pkg/ocm"
"github.com/open-cluster-management/discovery/pkg/api/domain/cluster_domain"
"github.com/open-cluster-management/discovery/pkg/api/services/auth_service"
"github.com/open-cluster-management/discovery/pkg/api/services/cluster_service"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var (
refreshInterval = 10 * time.Minute
refreshInterval = 1 * time.Hour
)

// DiscoveredClusterRefreshReconciler reconciles a DiscoveredClusterRefresh object
Expand Down Expand Up @@ -67,7 +69,7 @@ func (r *DiscoveredClusterRefreshReconciler) Reconcile(req ctrl.Request) (ctrl.R
Namespace: req.Namespace,
}, config); err != nil {
log.Error(err, "unable to fetch DiscoveryConfig")
return ctrl.Result{RequeueAfter: refreshInterval}, client.IgnoreNotFound(err)
return ctrl.Result{RequeueAfter: 10 * time.Second}, client.IgnoreNotFound(err)
}

// Get all refresh requests. If there are none then we were triggered by refresh interval
Expand All @@ -77,6 +79,7 @@ func (r *DiscoveredClusterRefreshReconciler) Reconcile(req ctrl.Request) (ctrl.R
return ctrl.Result{}, client.IgnoreNotFound(err)
}

// Get user token from secret provided in config
secretName := config.Spec.ProviderConnections[0]
ocmSecret := &corev1.Secret{}
err := r.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: req.Namespace}, ocmSecret)
Expand All @@ -88,7 +91,8 @@ func (r *DiscoveredClusterRefreshReconciler) Reconcile(req ctrl.Request) (ctrl.R
}
userToken := string(ocmSecret.Data["token"])

accessToken, err := auth.NewAccessToken(userToken)
// Request ephemeral access token with user token. This will be used for OCM requests
accessToken, err := auth_service.AuthClient.GetToken(userToken)
if err != nil {
return ctrl.Result{}, err
}
Expand All @@ -110,60 +114,53 @@ func (r *DiscoveredClusterRefreshReconciler) Reconcile(req ctrl.Request) (ctrl.R
var deleteClusters []discoveryv1.DiscoveredCluster
var unchangedClusters []discoveryv1.DiscoveredCluster

clusterRequest := ocm.ClusterRequest(config)
page := 1
size := 1000
for {
log.Info("Requesting OCM clusters", "page", page, "size", size)
newDiscoveredList, err := clusterRequest.Page(page).Size(size).Token(accessToken).Filter(config.Spec.Filters).Get(ctx)
if err != nil {
return ctrl.Result{}, err
}
clusterClient := cluster_service.ClusterClientGenerator.NewClient(cluster_domain.ClusterRequest{
Token: accessToken,
Filter: config.Spec.Filters,
})

// Merge newly discovered clusters with existing list
for _, cluster := range newDiscoveredList.Items {
discoveredCluster := ocm.DiscoveredCluster(cluster)
discoveredCluster.SetNamespace(req.Namespace)

// Assign dummy status
discoveredCluster.Spec.Subscription = discoveryv1.SubscriptionSpec{
Status: "Active",
SupportLevel: "None",
Managed: false,
CreatorID: "abc123",
}

// Add reference to secret used for authentication
discoveredCluster.Spec.ProviderConnections = nil
secretRef, err := ref.GetReference(r.Scheme, ocmSecret)
if err != nil {
log.Error(err, "unable to make reference to secret", "secret", secretRef)
}
discoveredCluster.Spec.ProviderConnections = append(discoveredCluster.Spec.ProviderConnections, *secretRef)

ind, exists := existing[discoveredCluster.Name]
if !exists {
// Newly discovered cluster
createClusters = append(createClusters, discoveredCluster)
delete(existing, discoveredCluster.Name)
continue
}
// Cluster has already been discovered. Check for changes.
if same(discoveredCluster, discoveredList.Items[ind]) {
unchangedClusters = append(unchangedClusters, discoveredCluster)
delete(existing, discoveredCluster.Name)
} else {
updated := discoveredList.Items[ind]
updated.Spec = discoveredCluster.Spec
updateClusters = append(updateClusters, updated)
delete(existing, discoveredCluster.Name)
}
newClusters, err := clusterClient.GetClusters()
if err != nil {
return ctrl.Result{}, err
}
for _, cluster := range newClusters {
// Build a DiscoveredCluster object from the cluster information
discoveredCluster := discoveredCluster(cluster)
discoveredCluster.SetNamespace(req.Namespace)

// Assign dummy status
discoveredCluster.Spec.Subscription = discoveryv1.SubscriptionSpec{
Status: "Active",
SupportLevel: "None",
Managed: false,
CreatorID: "abc123",
}

if len(newDiscoveredList.Items) < size {
break
// Add reference to secret used for authentication
discoveredCluster.Spec.ProviderConnections = nil
secretRef, err := ref.GetReference(r.Scheme, ocmSecret)
if err != nil {
log.Error(err, "unable to make reference to secret", "secret", secretRef)
}
discoveredCluster.Spec.ProviderConnections = append(discoveredCluster.Spec.ProviderConnections, *secretRef)

ind, exists := existing[discoveredCluster.Name]
if !exists {
// Newly discovered cluster
createClusters = append(createClusters, discoveredCluster)
delete(existing, discoveredCluster.Name)
continue
}
// Cluster has already been discovered. Check for changes.
if same(discoveredCluster, discoveredList.Items[ind]) {
unchangedClusters = append(unchangedClusters, discoveredCluster)
delete(existing, discoveredCluster.Name)
} else {
updated := discoveredList.Items[ind]
updated.Spec = discoveredCluster.Spec
updateClusters = append(updateClusters, updated)
delete(existing, discoveredCluster.Name)
}
page++
}

// Remaining clusters are no longer found by OCM and should be labeled for delete
Expand Down Expand Up @@ -274,3 +271,32 @@ func priorRequests(all *discoveryv1.DiscoveredClusterRefreshList, this *discover
}
return prior
}

// DiscoveredCluster ...
func discoveredCluster(cluster cluster_domain.Cluster) discoveryv1.DiscoveredCluster {
return discoveryv1.DiscoveredCluster{
TypeMeta: metav1.TypeMeta{
APIVersion: "operator.open-cluster-management.io/v1",
Kind: "DiscoveredCluster",
},
ObjectMeta: metav1.ObjectMeta{
Name: cluster.ID,
Namespace: "open-cluster-management",
},
Spec: discoveryv1.DiscoveredClusterSpec{
Console: cluster.Console.URL,
CreationTimestamp: cluster.CreationTimestamp,
ActivityTimestamp: cluster.ActivityTimestamp,
// ActivityTimestamp: metav1.NewTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)),
OpenshiftVersion: cluster.OpenShiftVersion,
Name: cluster.Name,
Region: cluster.Region.ID,
CloudProvider: cluster.CloudProvider.ID,
HealthState: cluster.HealthState,
State: cluster.State,
Product: cluster.Product.ID,
// IsManagedCluster: managedClusterNames[cluster.Name],
// APIURL: apiurl,
},
}
}
Loading

0 comments on commit 8022d40

Please sign in to comment.