Skip to content

Commit

Permalink
Fix Ansible posthook not creating AnsibleJob CR (#114)
Browse files Browse the repository at this point in the history
Signed-off-by: Mike Ng <ming@redhat.com>
  • Loading branch information
mikeshng authored Mar 11, 2022
1 parent e9b6cff commit ba2c012
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 27 deletions.
32 changes: 27 additions & 5 deletions build/e2e-kc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,39 @@ kubectl config use-context kind-hub
kubectl apply -f test/e2e/cases/05-ansiblejob/
sleep 10

if kubectl get subscriptions.apps.open-cluster-management.io ansible-hook -o yaml | grep lastprehookjob | grep prehook-test; then
echo "05-ansiblejob: found ansiblejob CR name in subscription output"
else
echo "05-ansiblejob: FAILED: ansiblejob CR name is not in the subscription output"
exit 1
fi
if kubectl get ansiblejobs.tower.ansible.com | grep prehook-test; then
echo "05-ansiblejob: found ansiblejobs.tower.ansible.com"
else
echo "05-ansiblejob: FAILED: ansiblejobs.tower.ansible.com not found"
exit 1
fi
if kubectl get subscriptions.apps.open-cluster-management.io ansible-hook -o yaml | grep lastprehookjob | grep prehook-test; then
echo "05-ansiblejob: found ansiblejob CR name in subscription output"
kubectl delete -f test/e2e/cases/05-ansiblejob/
sleep 5
echo "PASSED test case 05-ansiblejob"

### 06-ansiblejob-post
echo "STARTING test case 06-ansiblejob-post"
kubectl config use-context kind-hub
kubectl apply -f test/e2e/cases/06-ansiblejob-post/
sleep 30

if kubectl get subscriptions.apps.open-cluster-management.io ansible-hook -o yaml | grep lastposthookjob | grep posthook-test; then
echo "06-ansiblejob-post: found ansiblejob CR name in subscription output"
else
echo "05-ansiblejob: FAILED: ansiblejob CR name is not in the subscription output"
echo "06-ansiblejob-post: FAILED: ansiblejob CR name is not in the subscription output"
exit 1
fi

echo "PASSED test case 05-ansiblejob"
if kubectl get ansiblejobs.tower.ansible.com | grep posthook-test; then
echo "06-ansiblejob-post: found ansiblejobs.tower.ansible.com"
else
echo "06-ansiblejob-post: FAILED: ansiblejobs.tower.ansible.com not found"
kubectl get subscriptionreports.apps.open-cluster-management.io ansible-hook
exit 1
fi
echo "PASSED test case 06-ansiblejob-post"
48 changes: 26 additions & 22 deletions pkg/controller/mcmhub/mcmhub_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package mcmhub
import (
"context"
"fmt"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -45,6 +46,7 @@ import (
chnv1 "open-cluster-management.io/multicloud-operators-channel/pkg/apis/apps/v1"
appv1 "open-cluster-management.io/multicloud-operators-subscription/pkg/apis/apps/v1"
subv1 "open-cluster-management.io/multicloud-operators-subscription/pkg/apis/apps/v1"
appSubStatusV1alpha1 "open-cluster-management.io/multicloud-operators-subscription/pkg/apis/apps/v1alpha1"
"open-cluster-management.io/multicloud-operators-subscription/pkg/utils"
)

Expand Down Expand Up @@ -680,32 +682,34 @@ func (r *ReconcileSubscription) IsSubscriptionCompleted(subKey types.NamespacedN
return true, nil
}

// need to wait for managed cluster reporting back
// When placmentdecision doesn't have target cluster decision list, managed clusters status is empty.
// In this case, check the clusters list by checking the placementdecision
// If it's indeed empty cluster list then treat the subscription as completed.
managedStatus := subIns.Status.Statuses
if len(managedStatus) == 0 {
clusters, err := GetClustersByPlacement(subIns, r.Client, r.logger)
if err != nil {
return false, err
}
appsubReport := &appSubStatusV1alpha1.SubscriptionReport{}
if err := r.Get(context.TODO(), subKey, appsubReport); err != nil {
return false, err
}

return len(clusters) == 0, nil
// if there are no cluster matches or
// not all subscriptions are deployed/inprogress in matching clusters
if appsubReport.Summary.Clusters == "0" {
return false, nil
}

for cluster, cSt := range managedStatus {
if len(cSt.SubscriptionPackageStatus) == 0 {
continue
}
numClusters, err := strconv.Atoi(appsubReport.Summary.Clusters)
if err != nil {
return false, err
}

for pkg, pSt := range cSt.SubscriptionPackageStatus {
if pSt.Phase != subv1.SubscriptionSubscribed {
r.logger.Error(fmt.Errorf("cluster %s package %s is at status %s", cluster, pkg, pSt.Phase),
"subscription is not completed")
return false, nil
}
}
numDeployed, err := strconv.Atoi(appsubReport.Summary.Deployed)
if err != nil {
return false, err
}

numInProgress, err := strconv.Atoi(appsubReport.Summary.InProgress)
if err != nil {
return false, err
}

if (numDeployed + numInProgress) != numClusters {
return false, nil
}

return true, nil
Expand Down
9 changes: 9 additions & 0 deletions test/e2e/cases/06-ansiblejob-post/00-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: toweraccess
namespace: default
type: Opaque
stringData:
token: _token_here
host: _awx_ip_here_
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.0
creationTimestamp: null
name: ansiblejobs.tower.ansible.com
spec:
group: tower.ansible.com
names:
kind: AnsibleJob
listKind: AnsibleJobList
plural: ansiblejobs
singular: ansiblejob
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: AnsibleJob is the Schema for the ansiblejobs API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: AnsibleJobSpec defines the desired state of AnsibleJob
properties:
extra_vars:
type: object
inventory:
type: string
job_template_name:
type: string
tower_auth_secret:
description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster Important: Run "make" to regenerate code after modifying this file'
type: string
type: object
status:
description: AnsibleJobStatus defines the observed state of AnsibleJob
properties:
ansibleJobResult:
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state of cluster Important: Run "make" to regenerate code after modifying this file'
properties:
changed:
type: boolean
elapsed:
type: string
failed:
type: boolean
finished:
type: string
started:
type: string
status:
type: string
url:
type: string
type: object
conditions:
items:
description: Condition - the condition for the ansible operator.
properties:
ansibleResult:
description: bridging from https://github.com/operator-framework/operator-sdk/blob/master/internal/ansible/controller/status/types.go AnsibleResult - encapsulation of the ansible result.
properties:
changed:
type: integer
completion:
type: object
failures:
type: integer
ok:
type: integer
skipped:
type: integer
required:
- changed
- completion
- failures
- ok
- skipped
type: object
lastTransitionTime:
format: date-time
type: string
message:
type: string
reason:
type: string
status:
type: string
type:
description: ConditionType - type of condition
type: string
type: object
type: array
k8sJob:
properties:
created:
type: boolean
env:
properties:
secretNamespacedName:
type: string
templateName:
type: string
verifySSL:
type: boolean
type: object
message:
type: string
namespacedName:
type: string
type: object
message:
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
14 changes: 14 additions & 0 deletions test/e2e/cases/06-ansiblejob-post/01-placement-rule.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: apps.open-cluster-management.io/v1
kind: PlacementRule
metadata:
name: non-local-cluster
namespace: default
spec:
# apply to 1 cluster whoevers name not local-cluster
clusterReplicas: 1
clusterSelector:
matchExpressions:
- key: name
operator: NotIn
values:
- local-cluster
9 changes: 9 additions & 0 deletions test/e2e/cases/06-ansiblejob-post/02-channel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: apps.open-cluster-management.io/v1
kind: Channel
metadata:
name: git
namespace: default
spec:
type: git
pathname: https://github.com/open-cluster-management-io/multicloud-operators-subscription.git
17 changes: 17 additions & 0 deletions test/e2e/cases/06-ansiblejob-post/03-subscription.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: apps.open-cluster-management.io/v1
kind: Subscription
metadata:
name: ansible-hook
namespace: default
annotations:
apps.open-cluster-management.io/github-path: examples/ansible-post/resources
apps.open-cluster-management.io/github-branch: main
spec:
hooksecretref:
namespace: default
name: toweraccess
channel: default/git
placement:
placementRef:
kind: PlacementRule
name: non-local-cluster

0 comments on commit ba2c012

Please sign in to comment.