Skip to content

Commit 1d3aa60

Browse files
dymurrayShawn Hurley
authored andcommitted
pkg/ansible; Add support to watch cluster-scoped resources (#924) (#1031)
* pkg/ansible; Add support to watch cluster-scoped resources= * Update proxy command in images/scorecard-proxy
1 parent ee9f7ad commit 1d3aa60

File tree

13 files changed

+328
-127
lines changed

13 files changed

+328
-127
lines changed

doc/ansible/dev/advanced_options.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Some features can be overridden per resource via an annotation on that CR. The o
1414
| Reconcile Period | `reconcilePeriod` | time between reconcile runs for a particular CR | ansbile.operator-sdk/reconcile-period | 1m |
1515
| Manage Status | `manageStatus` | Allows the ansible operator to manage the conditions section of each resource's status section. | | true |
1616
| Watching Dependent Resources | `watchDependentResources` | Allows the ansible operator to dynamically watch resources that are created by ansible | | true |
17+
| Watching Cluster-Scoped Resources | `watchClusterScopedResources` | Allows the ansible operator to watch cluster-scoped resources that are created by ansible | | false |
1718
| Max Runner Artifacts | `maxRunnerArtifacts` | Manages the number of [artifact directories](https://ansible-runner.readthedocs.io/en/latest/intro.html#runner-artifacts-directory-hierarchy) that ansible runner will keep in the operator container for each individual resource. | ansible.operator-sdk/max-runner-artifacts | 20 |
1819

1920

images/scorecard-proxy/cmd/proxy/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"os"
2020

2121
proxy "github.com/operator-framework/operator-sdk/pkg/ansible/proxy"
22+
"github.com/operator-framework/operator-sdk/pkg/ansible/proxy/controllermap"
2223
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
2324

2425
log "github.com/sirupsen/logrus"
@@ -47,7 +48,7 @@ func main() {
4748
}
4849

4950
done := make(chan error)
50-
cMap := proxy.NewControllerMap()
51+
cMap := controllermap.NewControllerMap()
5152

5253
// start the proxy
5354
err = proxy.Run(done, proxy.Options{

pkg/ansible/controller/controller.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ var log = logf.Log.WithName("ansible-controller")
4040

4141
// Options - options for your controller
4242
type Options struct {
43-
EventHandlers []events.EventHandler
44-
LoggingLevel events.LogLevel
45-
Runner runner.Runner
46-
GVK schema.GroupVersionKind
47-
ReconcilePeriod time.Duration
48-
ManageStatus bool
49-
WatchDependentResources bool
43+
EventHandlers []events.EventHandler
44+
LoggingLevel events.LogLevel
45+
Runner runner.Runner
46+
GVK schema.GroupVersionKind
47+
ReconcilePeriod time.Duration
48+
ManageStatus bool
49+
WatchDependentResources bool
50+
WatchClusterScopedResources bool
5051
}
5152

5253
// Add - Creates a new ansible operator controller and adds it to the manager

pkg/ansible/operator/operator.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121

2222
"github.com/operator-framework/operator-sdk/pkg/ansible/controller"
2323
"github.com/operator-framework/operator-sdk/pkg/ansible/flags"
24-
"github.com/operator-framework/operator-sdk/pkg/ansible/proxy"
24+
"github.com/operator-framework/operator-sdk/pkg/ansible/proxy/controllermap"
2525
"github.com/operator-framework/operator-sdk/pkg/ansible/runner"
2626

2727
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -32,7 +32,7 @@ import (
3232
// Run - A blocking function which starts a controller-runtime manager
3333
// It starts an Operator by reading in the values in `./watches.yaml`, adds a controller
3434
// to the manager, and finally running the manager.
35-
func Run(done chan error, mgr manager.Manager, f *flags.AnsibleOperatorFlags, cMap *proxy.ControllerMap) {
35+
func Run(done chan error, mgr manager.Manager, f *flags.AnsibleOperatorFlags, cMap *controllermap.ControllerMap) {
3636
watches, err := runner.NewFromWatches(f.WatchesFile)
3737
if err != nil {
3838
logf.Log.WithName("manager").Error(err, "Failed to get watches")
@@ -57,7 +57,12 @@ func Run(done chan error, mgr manager.Manager, f *flags.AnsibleOperatorFlags, cM
5757
done <- errors.New("failed to add controller")
5858
return
5959
}
60-
cMap.Store(o.GVK, *ctr, runner.GetWatchDependentResources())
60+
cMap.Store(o.GVK, &controllermap.ControllerMapContents{Controller: *ctr,
61+
WatchDependentResources: runner.GetWatchDependentResources(),
62+
WatchClusterScopedResources: runner.GetWatchClusterScopedResources(),
63+
WatchMap: controllermap.NewWatchMap(),
64+
UIDMap: controllermap.NewUIDMap(),
65+
})
6166
}
6267
done <- mgr.Start(c)
6368
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// Copyright 2018 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package controllermap
16+
17+
import (
18+
"sync"
19+
20+
"k8s.io/apimachinery/pkg/runtime/schema"
21+
"k8s.io/apimachinery/pkg/types"
22+
"sigs.k8s.io/controller-runtime/pkg/controller"
23+
)
24+
25+
// ControllerMap - map of GVK to ControllerMapContents
26+
type ControllerMap struct {
27+
mutex sync.RWMutex
28+
internal map[schema.GroupVersionKind]*ControllerMapContents
29+
}
30+
31+
// UIDMap - map of UID to namespaced name of owner
32+
type UIDMap struct {
33+
mutex sync.RWMutex
34+
internal map[types.UID]types.NamespacedName
35+
}
36+
37+
// WatchMap - map of GVK to interface. Determines if resource is being watched already
38+
type WatchMap struct {
39+
mutex sync.RWMutex
40+
internal map[schema.GroupVersionKind]interface{}
41+
}
42+
43+
// ControllerMapContents- Contains internal data associated with each controller
44+
type ControllerMapContents struct {
45+
Controller controller.Controller
46+
WatchDependentResources bool
47+
WatchClusterScopedResources bool
48+
WatchMap *WatchMap
49+
UIDMap *UIDMap
50+
}
51+
52+
// NewControllerMap returns a new object that contains a mapping between GVK
53+
// and ControllerMapContents object
54+
func NewControllerMap() *ControllerMap {
55+
return &ControllerMap{
56+
internal: make(map[schema.GroupVersionKind]*ControllerMapContents),
57+
}
58+
}
59+
60+
// NewWatchMap - returns a new object that maps GVK to interface to determine
61+
// if resource is being watched
62+
func NewWatchMap() *WatchMap {
63+
return &WatchMap{
64+
internal: make(map[schema.GroupVersionKind]interface{}),
65+
}
66+
}
67+
68+
// NewUIDMap - returns a new object that maps UID to namespaced name of owner
69+
func NewUIDMap() *UIDMap {
70+
return &UIDMap{
71+
internal: make(map[types.UID]types.NamespacedName),
72+
}
73+
}
74+
75+
// Get - Returns a ControllerMapContents given a GVK as the key. `ok`
76+
// determines if the key exists
77+
func (cm *ControllerMap) Get(key schema.GroupVersionKind) (value *ControllerMapContents, ok bool) {
78+
cm.mutex.RLock()
79+
defer cm.mutex.RUnlock()
80+
value, ok = cm.internal[key]
81+
return value, ok
82+
}
83+
84+
// Delete - Deletes associated GVK to controller mapping from the ControllerMap
85+
func (cm *ControllerMap) Delete(key schema.GroupVersionKind) {
86+
cm.mutex.Lock()
87+
defer cm.mutex.Unlock()
88+
delete(cm.internal, key)
89+
}
90+
91+
// Store - Adds a new GVK to controller mapping
92+
func (cm *ControllerMap) Store(key schema.GroupVersionKind, value *ControllerMapContents) {
93+
cm.mutex.Lock()
94+
defer cm.mutex.Unlock()
95+
cm.internal[key] = value
96+
}
97+
98+
// Get - Checks if GVK is already watched
99+
func (wm *WatchMap) Get(key schema.GroupVersionKind) (value interface{}, ok bool) {
100+
wm.mutex.RLock()
101+
defer wm.mutex.RUnlock()
102+
value, ok = wm.internal[key]
103+
return value, ok
104+
}
105+
106+
// Delete - Deletes associated watches for a specific GVK
107+
func (wm *WatchMap) Delete(key schema.GroupVersionKind) {
108+
wm.mutex.Lock()
109+
defer wm.mutex.Unlock()
110+
delete(wm.internal, key)
111+
}
112+
113+
// Store - Adds a new GVK to be watched
114+
func (wm *WatchMap) Store(key schema.GroupVersionKind) {
115+
wm.mutex.Lock()
116+
defer wm.mutex.Unlock()
117+
wm.internal[key] = nil
118+
}
119+
120+
// Get - Returns a NamespacedName of the owner given a UID
121+
func (um *UIDMap) Get(key types.UID) (value types.NamespacedName, ok bool) {
122+
um.mutex.RLock()
123+
defer um.mutex.RUnlock()
124+
value, ok = um.internal[key]
125+
return value, ok
126+
}
127+
128+
// Delete - Deletes associated UID to NamespacedName mapping
129+
func (um *UIDMap) Delete(key types.UID) {
130+
um.mutex.Lock()
131+
defer um.mutex.Unlock()
132+
delete(um.internal, key)
133+
}
134+
135+
// Store - Adds a new UID to NamespacedName mapping
136+
func (um *UIDMap) Store(key types.UID, value types.NamespacedName) {
137+
um.mutex.Lock()
138+
defer um.mutex.Unlock()
139+
um.internal[key] = value
140+
}

pkg/ansible/proxy/kubeconfig/kubeconfig.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,19 @@ type values struct {
6464
Namespace string
6565
}
6666

67+
type NamespacedOwnerReference struct {
68+
metav1.OwnerReference
69+
Namespace string
70+
}
71+
6772
// Create renders a kubeconfig template and writes it to disk
6873
func Create(ownerRef metav1.OwnerReference, proxyURL string, namespace string) (*os.File, error) {
74+
nsOwnerRef := NamespacedOwnerReference{OwnerReference: ownerRef, Namespace: namespace}
6975
parsedURL, err := url.Parse(proxyURL)
7076
if err != nil {
7177
return nil, err
7278
}
73-
ownerRefJSON, err := json.Marshal(ownerRef)
79+
ownerRefJSON, err := json.Marshal(nsOwnerRef)
7480
if err != nil {
7581
return nil, err
7682
}

0 commit comments

Comments
 (0)