forked from juju/juju
/
groups.go
146 lines (131 loc) · 3.66 KB
/
groups.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright 2020 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package gen
import (
reflect "reflect"
"strings"
facade "github.com/DavinZhang/juju/apiserver/facade"
"github.com/juju/errors"
"github.com/juju/rpcreflect"
)
// FacadeGroup defines the grouping you want to export.
type FacadeGroup string
const (
// Latest gets the latest facades from all the facades.
Latest FacadeGroup = "latest"
// All gets all the facades no matter the version.
All FacadeGroup = "all"
// Client facades returns just the client facades along with some required
// facades that the client can use.
Client FacadeGroup = "client"
// JIMM facade group defines a very select set of facades that only work
// with JIMM. This does not include the JIMM facade as defined in JIMM.
JIMM FacadeGroup = "jimm"
)
// ParseFacadeGroup will attempt to parse the facade group
func ParseFacadeGroup(s string) (FacadeGroup, error) {
switch s {
case "latest", "all", "client", "jimm":
return FacadeGroup(s), nil
default:
return FacadeGroup(""), errors.NotValidf("facade group")
}
}
// Filter the facades based on the group.
func Filter(g FacadeGroup, facades []facade.Details, registry Registry) []facade.Details {
switch g {
case Latest:
return latestFacades(facades)
case All:
return allFacades(facades)
case Client:
return clientFacades(facades, registry)
case JIMM:
return jimmFacades(facades)
}
return facades
}
func latestFacades(facades []facade.Details) []facade.Details {
latest := make(map[string]facade.Details)
for _, facade := range facades {
if f, ok := latest[facade.Name]; ok && facade.Version < f.Version {
continue
}
latest[facade.Name] = facade
}
latestFacades := make([]facade.Details, 0, len(latest))
for _, v := range latest {
latestFacades = append(latestFacades, v)
}
return latestFacades
}
func allFacades(facades []facade.Details) []facade.Details {
return facades
}
func clientFacades(facades []facade.Details, registry Registry) []facade.Details {
required := map[string]struct{}{
"Admin": {},
"AllWatcher": {},
"AllModelWatcher": {},
"ModelSummaryManager": {},
"Pinger": {},
}
results := make([]facade.Details, 0)
latest := latestFacades(facades)
for _, v := range latest {
if _, ok := required[v.Name]; ok {
results = append(results, v)
continue
}
var objType *rpcreflect.ObjType
kind, err := registry.GetType(v.Name, v.Version)
if err == nil {
objType = rpcreflect.ObjTypeOf(kind)
} else {
objType = rpcreflect.ObjTypeOf(v.Type)
if objType == nil {
continue
}
}
pkg := packageName(objType.GoType())
if !strings.HasPrefix(pkg, "github.com/DavinZhang/juju/apiserver/facades/client/") {
continue
}
results = append(results, v)
}
return results
}
func jimmFacades(facades []facade.Details) []facade.Details {
// The JIMM facades are the ones that are baked into JIMM directly. If JIMM
// ever updates it's baked in facade schemas, then we should also update the
// ones here.
required := map[string][]int{
"Bundle": {1},
"Cloud": {1, 2, 3, 4, 5},
"Controller": {3, 4, 5, 6, 7, 8, 9, 10, 11},
"ModelManager": {2, 3, 4, 5},
"ModelSummaryManager": {1},
"Pinger": {1},
"UserManager": {1},
}
result := make([]facade.Details, 0)
for _, v := range facades {
versions, ok := required[v.Name]
if !ok {
continue
}
for _, i := range versions {
if v.Version == i {
result = append(result, v)
break
}
}
}
return result
}
func packageName(v reflect.Type) string {
if v.Kind() == reflect.Ptr {
return v.Elem().PkgPath()
}
return v.PkgPath()
}