Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / sigs.k8s.io / controller-tools / pkg / internal / codegen / parse / parser.go
1 /*
2 Copyright 2018 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package parse
18
19 import (
20         "bufio"
21         "go/build"
22         "log"
23         "os"
24         "path/filepath"
25         "strings"
26
27         "github.com/pkg/errors"
28         rbacv1 "k8s.io/api/rbac/v1"
29         "k8s.io/apimachinery/pkg/apis/meta/v1"
30         "k8s.io/apimachinery/pkg/util/sets"
31         "k8s.io/gengo/args"
32         "k8s.io/gengo/generator"
33         "k8s.io/gengo/types"
34         "sigs.k8s.io/controller-tools/pkg/internal/codegen"
35 )
36
37 // APIs is the information of a collection of API
38 type APIs struct {
39         context         *generator.Context
40         arguments       *args.GeneratorArgs
41         Domain          string
42         VersionedPkgs   sets.String
43         UnversionedPkgs sets.String
44         APIsPkg         string
45         APIsPkgRaw      *types.Package
46         GroupNames      sets.String
47
48         APIs        *codegen.APIs
49         Controllers []codegen.Controller
50
51         ByGroupKindVersion    map[string]map[string]map[string]*codegen.APIResource
52         ByGroupVersionKind    map[string]map[string]map[string]*codegen.APIResource
53         SubByGroupVersionKind map[string]map[string]map[string]*types.Type
54         Groups                map[string]types.Package
55         Rules                 []rbacv1.PolicyRule
56         Informers             map[v1.GroupVersionKind]bool
57 }
58
59 // NewAPIs returns a new APIs instance with given context.
60 func NewAPIs(context *generator.Context, arguments *args.GeneratorArgs, domain, apisPkg string) *APIs {
61         b := &APIs{
62                 context:   context,
63                 arguments: arguments,
64                 Domain:    domain,
65                 APIsPkg:   apisPkg,
66         }
67         b.parsePackages()
68         b.parseGroupNames()
69         b.parseIndex()
70         b.parseAPIs()
71         b.parseCRDs()
72         if len(b.Domain) == 0 {
73                 b.parseDomain()
74         }
75         return b
76 }
77
78 // parseGroupNames initializes b.GroupNames with the set of all groups
79 func (b *APIs) parseGroupNames() {
80         b.GroupNames = sets.String{}
81         for p := range b.UnversionedPkgs {
82                 pkg := b.context.Universe[p]
83                 if pkg == nil {
84                         // If the input had no Go files, for example.
85                         continue
86                 }
87                 b.GroupNames.Insert(filepath.Base(p))
88         }
89 }
90
91 // parsePackages parses out the sets of Versioned, Unversioned packages and identifies the root Apis package.
92 func (b *APIs) parsePackages() {
93         b.VersionedPkgs = sets.NewString()
94         b.UnversionedPkgs = sets.NewString()
95         for _, o := range b.context.Order {
96                 if IsAPIResource(o) {
97                         versioned := o.Name.Package
98                         b.VersionedPkgs.Insert(versioned)
99
100                         unversioned := filepath.Dir(versioned)
101                         b.UnversionedPkgs.Insert(unversioned)
102                 }
103         }
104 }
105
106 // parseDomain parses the domain from the apis/doc.go file comment "// +domain=YOUR_DOMAIN".
107 func (b *APIs) parseDomain() {
108         pkg := b.context.Universe[b.APIsPkg]
109         if pkg == nil {
110                 // If the input had no Go files, for example.
111                 panic(errors.Errorf("Missing apis package."))
112         }
113         comments := Comments(pkg.Comments)
114         b.Domain = comments.getTag("domain", "=")
115         if len(b.Domain) == 0 {
116                 b.Domain = parseDomainFromFiles(b.context.Inputs)
117                 if len(b.Domain) == 0 {
118                         panic("Could not find string matching // +domain=.+ in apis/doc.go")
119                 }
120         }
121 }
122
123 func parseDomainFromFiles(paths []string) string {
124         var domain string
125         for _, path := range paths {
126                 if strings.HasSuffix(path, "pkg/apis") {
127                         filePath := strings.Join([]string{build.Default.GOPATH, "src", path, "doc.go"}, "/")
128                         lines := []string{}
129
130                         file, err := os.Open(filePath)
131                         if err != nil {
132                                 log.Fatal(err)
133                         }
134                         defer file.Close()
135                         scanner := bufio.NewScanner(file)
136                         for scanner.Scan() {
137                                 if strings.HasPrefix(scanner.Text(), "//") {
138                                         lines = append(lines, strings.Replace(scanner.Text(), "// ", "", 1))
139                                 }
140                         }
141                         if err := scanner.Err(); err != nil {
142                                 log.Fatal(err)
143                         }
144
145                         comments := Comments(lines)
146                         domain = comments.getTag("domain", "=")
147                         break
148                 }
149         }
150         return domain
151 }