@@ -16,6 +16,7 @@ package add
16
16
17
17
import (
18
18
"bytes"
19
+ "errors"
19
20
"fmt"
20
21
"io/ioutil"
21
22
"log"
@@ -25,7 +26,10 @@ import (
25
26
"github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/cmdutil"
26
27
"github.com/operator-framework/operator-sdk/pkg/scaffold"
27
28
29
+ "github.com/ghodss/yaml"
28
30
"github.com/spf13/cobra"
31
+ rbacv1beta1 "k8s.io/api/rbac/v1beta1"
32
+ cgoscheme "k8s.io/client-go/kubernetes/scheme"
29
33
)
30
34
31
35
var (
@@ -162,8 +166,64 @@ func apiRun(cmd *cobra.Command, args []string) {
162
166
log .Fatalf ("failed to create %v: %v" , filePath , err )
163
167
}
164
168
165
- // TODO: append rbac rule to deploy/rbac/role.yaml
169
+ // update deploy/role.yaml for the given resource r.
170
+ if err := updateRoleForResource (r , fullProjectPath ); err != nil {
171
+ log .Fatalf ("failed to update the RBAC manifest for the resource (%v, %v): %v" , r .APIVersion , r .Kind , err )
172
+ }
173
+ }
166
174
175
+ func updateRoleForResource (r * scaffold.Resource , fullProjectPath string ) error {
176
+ // append rbac rule to deploy/role.yaml
177
+ roleFilePath := filepath .Join (fullProjectPath , "deploy" , "role.yaml" )
178
+ roleYAML , err := ioutil .ReadFile (roleFilePath )
179
+ if err != nil {
180
+ return fmt .Errorf ("failed to read role manifest %v: %v" , roleFilePath , err )
181
+ }
182
+ obj , _ , err := cgoscheme .Codecs .UniversalDeserializer ().Decode (roleYAML , nil , nil )
183
+ if err != nil {
184
+ return fmt .Errorf ("failed to decode role manifest %v: %v" , roleFilePath , err )
185
+ }
186
+ switch role := obj .(type ) {
187
+ // TODO: use rbac/v1.
188
+ case * rbacv1beta1.Role :
189
+ pr := & rbacv1beta1.PolicyRule {}
190
+ apiGroupFound := false
191
+ for i := range role .Rules {
192
+ if role .Rules [i ].APIGroups [0 ] == r .FullGroup {
193
+ apiGroupFound = true
194
+ pr = & role .Rules [i ]
195
+ break
196
+ }
197
+ }
198
+ // check if the resource already exists
199
+ for _ , resource := range pr .Resources {
200
+ if resource == r .Resource {
201
+ log .Printf ("deploy/role.yaml RBAC rules already up to date for the resource (%v, %v)" , r .APIVersion , r .Kind )
202
+ return nil
203
+ }
204
+ }
205
+
206
+ pr .Resources = append (pr .Resources , r .Resource )
207
+ // create a new apiGroup if not found.
208
+ if ! apiGroupFound {
209
+ pr .APIGroups = []string {r .FullGroup }
210
+ pr .Resources = []string {r .Resource }
211
+ pr .Verbs = []string {"*" }
212
+ role .Rules = append (role .Rules , * pr )
213
+ }
214
+ // update role.yaml
215
+ data , err := yaml .Marshal (& role )
216
+ if err != nil {
217
+ return fmt .Errorf ("failed to marshal role(%+v): %v" , role , err )
218
+ }
219
+ if err := ioutil .WriteFile (roleFilePath , data , cmdutil .DefaultFileMode ); err != nil {
220
+ return fmt .Errorf ("failed to update %v: %v" , roleFilePath , err )
221
+ }
222
+ default :
223
+ return errors .New ("failed to parse role.yaml as a role" )
224
+ }
225
+ // not reachable
226
+ return nil
167
227
}
168
228
169
229
// TODO: Make the utils below common in pkg/cmd/util
0 commit comments