"Go describe role 구현"의 두 판 사이의 차이

(새 문서: ==개요== ;Go describe role 구현 ;Go describe clusterrole 구현 <syntaxhighlight lang='go' run> package main import ( "fmt" "reflect" "strings" "gopkg.in/yaml.v3" ) var ya...)
 
 
(같은 사용자의 중간 판 하나는 보이지 않습니다)
9번째 줄: 9번째 줄:
"fmt"
"fmt"
"reflect"
"reflect"
"sort"
"strings"
"strings"


15번째 줄: 16번째 줄:


var yamls = []string{
var yamls = []string{
`
kind: ClusterRole
metadata:
  name: system:public-info-viewer
rules:
- nonResourceURLs:
  - /healthz
  - /livez
  - /readyz
  - /version
  - /version/
  verbs:
  - get
`,
`
`
apiVersion: rbac.authorization.k8s.io/v1
apiVersion: rbac.authorization.k8s.io/v1
702번째 줄: 717번째 줄:


type Metadata struct {
type Metadata struct {
Name string `yaml:"name"`
Name     string `yaml:"name"`
Namespace string `yaml:"namespace,omitempty"`
}
}


type Rule struct {
type Rule struct {
Verbs          []string `yaml:"verbs"`
APIGroups      []string `yaml:"apiGroups"`
APIGroups      []string `yaml:"apiGroups"`
NonResourceURLs []string `yaml:"nonResourceURLs"`
Resources      []string `yaml:"resources"`
Resources      []string `yaml:"resources"`
ResourceNames  []string `yaml:"resourceNames"`
ResourceNames  []string `yaml:"resourceNames"`
Verbs          []string `yaml:"verbs"`
NonResourceURLs []string `yaml:"nonResourceURLs"`
}
 
func transposeNonResourceURLs(rules []Rule) []Rule {
var newRules []Rule
for _, rule := range rules {
if len(rule.NonResourceURLs) < 2 {
newRules = append(newRules, rule)
continue
}
var newRule = rule
for _, url := range rule.NonResourceURLs {
newRule.NonResourceURLs = []string{url}
newRules = append(newRules, newRule)
}
}
return newRules
}
}


type PolicyRule struct {
type SortableRuleSlice []Rule
Resource        string
 
NonResourceURLs []string
func (s SortableRuleSlice) Len() int      { return len(s) }
ResourceNames   []string
func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
Verbs           []string
func (s SortableRuleSlice) Less(i, j int) bool {
// {Verbs:[*] APIGroups:[] Resources:[*.*] ResourceNames:[] NonResourceURLs:[]}
// {Verbs:[*] APIGroups:[] Resources:[] ResourceNames:[] NonResourceURLs:[*]}
// {Verbs:[create delete deletecollection patch update get list watch] APIGroups:[] Resources:[services] ResourceNames:[] NonResourceURLs:[]}
// {Verbs:[create delete deletecollection patch update get list watch] APIGroups:[acme.cert-manager.io] Resources:[challenges.acme.cert-manager.io] ResourceNames:[] NonResourceURLs:[]}
return strings.Compare(fmt.Sprintf("%+v", s[i]), fmt.Sprintf("%+v", s[j])) < 0
}
}


func describe(role Role) {
func describe(role Role) {
policyRules := []PolicyRule{}
rules := []Rule{}
for _, r := range role.Rules {
for _, r := range role.Rules {
if len(r.APIGroups) == 0 {
if len(r.APIGroups) == 0 {
policyRules = append(policyRules, PolicyRule{
rules = append(rules, Rule{
Resource:       "",
Verbs:           r.Verbs,
Resources:      []string{},
ResourceNames:  r.ResourceNames,
NonResourceURLs: r.NonResourceURLs,
NonResourceURLs: r.NonResourceURLs,
ResourceNames:  r.ResourceNames,
Verbs:          r.Verbs,
})
})
continue
continue
738번째 줄: 775번째 줄:
}
}
for _, resource := range r.Resources {
for _, resource := range r.Resources {
parts := strings.Split(resource, "/")
var parts = strings.Split(resource, "/")
if len(parts) == 1 {
if len(parts) == 1 {
resource = resource + postfix
resource = resource + postfix
744번째 줄: 781번째 줄:
resource = parts[0] + postfix + "/" + parts[1]
resource = parts[0] + postfix + "/" + parts[1]
}
}
var resources = []string{resource}
var idx = -1
var idx = -1
for i, rule := range policyRules {
for i, rule := range rules {
if rule.Resource != resource {
if !reflect.DeepEqual(rule.Resources, resources) {
continue
continue
}
}
759번째 줄: 797번째 줄:
}
}
if idx >= 0 {
if idx >= 0 {
policyRules[idx].Verbs = append(policyRules[idx].Verbs, r.Verbs...)
rules[idx].Verbs = append(rules[idx].Verbs, r.Verbs...)
} else {
} else {
policyRules = append(policyRules, PolicyRule{
rules = append(rules, Rule{
Resource:       resource,
Verbs:           r.Verbs,
APIGroups:      []string{apiGroup},
Resources:      resources,
ResourceNames:  r.ResourceNames,
NonResourceURLs: r.NonResourceURLs,
NonResourceURLs: r.NonResourceURLs,
ResourceNames:  r.ResourceNames,
Verbs:          r.Verbs,
})
})
}
}
771번째 줄: 810번째 줄:
}
}
}
}
rules = transposeNonResourceURLs(rules)
sort.Stable(SortableRuleSlice(rules))


fmt.Println("---")
fmt.Println("---")
fmt.Println("Kind:", role.Kind)
fmt.Println("Name:", role.Metadata.Name)
fmt.Println("Name:", role.Metadata.Name)
if role.Kind == "Role" {
fmt.Println("Namespace:", role.Metadata.Namespace)
}
fmt.Println("PolicyRule:")
fmt.Println("PolicyRule:")
fmt.Printf("  %-50s  %v  %v  %s\n", "Resources", "Non-Resource URLs", "Resource Names", "Verbs")
fmt.Printf("  %-50s  %v  %v  %s\n", "Resources", "Non-Resource URLs", "Resource Names", "Verbs")
for _, r := range policyRules {
for _, r := range rules {
fmt.Printf("  %-50s  %v  %v  %s\n", r.Resource, r.NonResourceURLs, r.ResourceNames, r.Verbs)
var resource = ""
if len(r.Resources) > 0 {
resource = r.Resources[0]
}
fmt.Printf("  %-50s  %v  %v  %s\n", resource, r.NonResourceURLs, r.ResourceNames, r.Verbs)
}
}
}
}

2024년 4월 2일 (화) 12:06 기준 최신판

1 개요[ | ]

Go describe role 구현
Go describe clusterrole 구현
package main

import (
	"fmt"
	"reflect"
	"sort"
	"strings"

	"gopkg.in/yaml.v3"
)

var yamls = []string{
	`
kind: ClusterRole
metadata:
  name: system:public-info-viewer
rules:
- nonResourceURLs:
  - /healthz
  - /livez
  - /readyz
  - /version
  - /version/
  verbs:
  - get
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-admin
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: view
rules:
- apiGroups:
  - cert-manager.io
  resources:
  - certificates
  - certificaterequests
  - issuers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - acme.cert-manager.io
  resources:
  - challenges
  - orders
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - notification.toolkit.fluxcd.io
  - source.toolkit.fluxcd.io
  - helm.toolkit.fluxcd.io
  - image.toolkit.fluxcd.io
  - kustomize.toolkit.fluxcd.io
  resources:
  - '*'
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - get
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - watch
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: system:controller:bootstrap-signer
  namespace: kube-public
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resourceNames:
  - cluster-info
  resources:
  - configmaps
  verbs:
  - update
- apiGroups:
  - ""
  - events.k8s.io
  resources:
  - events
  verbs:
  - create
  - patch
  - update
`,
	`
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: edit
rules:
- apiGroups:
  - cert-manager.io
  resources:
  - certificates
  - certificaterequests
  - issuers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - cert-manager.io
  resources:
  - certificates/status
  verbs:
  - update
- apiGroups:
  - acme.cert-manager.io
  resources:
  - challenges
  - orders
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - cert-manager.io
  resources:
  - certificates
  - certificaterequests
  - issuers
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - acme.cert-manager.io
  resources:
  - challenges
  - orders
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - notification.toolkit.fluxcd.io
  - source.toolkit.fluxcd.io
  - helm.toolkit.fluxcd.io
  - image.toolkit.fluxcd.io
  - kustomize.toolkit.fluxcd.io
  resources:
  - '*'
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - notification.toolkit.fluxcd.io
  - source.toolkit.fluxcd.io
  - helm.toolkit.fluxcd.io
  - image.toolkit.fluxcd.io
  - kustomize.toolkit.fluxcd.io
  resources:
  - '*'
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  - secrets
  - services/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - ""
  resources:
  - pods
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - replicationcontrollers
  - replicationcontrollers/scale
  - secrets
  - serviceaccounts
  - services
  - services/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - apps
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - replicasets
  - replicasets/scale
  - statefulsets
  - statefulsets/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - ingresses
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - networkpolicies
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - delete
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - deletecollection
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - patch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - update
- apiGroups:
  - ""
  resources:
  - pods/eviction
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - serviceaccounts/token
  verbs:
  - create
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - create
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - delete
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - deletecollection
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - get
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - list
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - patch
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - update
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - watch
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - get
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - watch
`,
}

type Role struct {
	ApiVersion string   `yaml:"apiVersion"`
	Kind       string   `yaml:"kind"`
	Metadata   Metadata `yaml:"metadata"`
	Rules      []Rule   `yaml:"rules"`
}

type Metadata struct {
	Name      string `yaml:"name"`
	Namespace string `yaml:"namespace,omitempty"`
}

type Rule struct {
	Verbs           []string `yaml:"verbs"`
	APIGroups       []string `yaml:"apiGroups"`
	Resources       []string `yaml:"resources"`
	ResourceNames   []string `yaml:"resourceNames"`
	NonResourceURLs []string `yaml:"nonResourceURLs"`
}

func transposeNonResourceURLs(rules []Rule) []Rule {
	var newRules []Rule
	for _, rule := range rules {
		if len(rule.NonResourceURLs) < 2 {
			newRules = append(newRules, rule)
			continue
		}
		var newRule = rule
		for _, url := range rule.NonResourceURLs {
			newRule.NonResourceURLs = []string{url}
			newRules = append(newRules, newRule)
		}
	}
	return newRules
}

type SortableRuleSlice []Rule

func (s SortableRuleSlice) Len() int      { return len(s) }
func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortableRuleSlice) Less(i, j int) bool {
	// {Verbs:[*] APIGroups:[] Resources:[*.*] ResourceNames:[] NonResourceURLs:[]}
	// {Verbs:[*] APIGroups:[] Resources:[] ResourceNames:[] NonResourceURLs:[*]}
	// {Verbs:[create delete deletecollection patch update get list watch] APIGroups:[] Resources:[services] ResourceNames:[] NonResourceURLs:[]}
	// {Verbs:[create delete deletecollection patch update get list watch] APIGroups:[acme.cert-manager.io] Resources:[challenges.acme.cert-manager.io] ResourceNames:[] NonResourceURLs:[]}
	return strings.Compare(fmt.Sprintf("%+v", s[i]), fmt.Sprintf("%+v", s[j])) < 0
}

func describe(role Role) {
	rules := []Rule{}
	for _, r := range role.Rules {
		if len(r.APIGroups) == 0 {
			rules = append(rules, Rule{
				Verbs:           r.Verbs,
				Resources:       []string{},
				ResourceNames:   r.ResourceNames,
				NonResourceURLs: r.NonResourceURLs,
			})
			continue
		}
		for _, apiGroup := range r.APIGroups {
			var postfix = ""
			if len(apiGroup) > 0 {
				postfix += "." + apiGroup
			}
			for _, resource := range r.Resources {
				var parts = strings.Split(resource, "/")
				if len(parts) == 1 {
					resource = resource + postfix
				} else {
					resource = parts[0] + postfix + "/" + parts[1]
				}
				var resources = []string{resource}
				var idx = -1
				for i, rule := range rules {
					if !reflect.DeepEqual(rule.Resources, resources) {
						continue
					}
					if !reflect.DeepEqual(rule.NonResourceURLs, r.NonResourceURLs) {
						continue
					}
					if !reflect.DeepEqual(rule.ResourceNames, r.ResourceNames) {
						continue
					}
					idx = i
					break
				}
				if idx >= 0 {
					rules[idx].Verbs = append(rules[idx].Verbs, r.Verbs...)
				} else {
					rules = append(rules, Rule{
						Verbs:           r.Verbs,
						APIGroups:       []string{apiGroup},
						Resources:       resources,
						ResourceNames:   r.ResourceNames,
						NonResourceURLs: r.NonResourceURLs,
					})
				}
			}
		}
	}
	rules = transposeNonResourceURLs(rules)
	sort.Stable(SortableRuleSlice(rules))

	fmt.Println("---")
	fmt.Println("Kind:", role.Kind)
	fmt.Println("Name:", role.Metadata.Name)
	if role.Kind == "Role" {
		fmt.Println("Namespace:", role.Metadata.Namespace)
	}
	fmt.Println("PolicyRule:")
	fmt.Printf("  %-50s  %v  %v  %s\n", "Resources", "Non-Resource URLs", "Resource Names", "Verbs")
	for _, r := range rules {
		var resource = ""
		if len(r.Resources) > 0 {
			resource = r.Resources[0]
		}
		fmt.Printf("  %-50s  %v  %v  %s\n", resource, r.NonResourceURLs, r.ResourceNames, r.Verbs)
	}
}

func main() {
	var role Role
	for _, y := range yamls {
		yaml.Unmarshal([]byte(y), &role)
		describe(role)
	}
}

2 같이 보기[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}