Skip to content

Commit 18903e5

Browse files
authored
Merge pull request kubernetes#2387 from justaugustus/cleanup
Repo package cleanups/refactors
2 parents 5d6d935 + 685eecf commit 18903e5

34 files changed

+869
-375
lines changed

api/approval.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
Copyright 2021 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 api
18+
19+
import (
20+
"bufio"
21+
"bytes"
22+
"io"
23+
24+
"github.com/go-playground/validator/v10"
25+
"github.com/pkg/errors"
26+
"gopkg.in/yaml.v3"
27+
)
28+
29+
type PRRApprovals []*PRRApproval
30+
31+
func (p *PRRApprovals) AddPRRApproval(prrApproval *PRRApproval) {
32+
*p = append(*p, prrApproval)
33+
}
34+
35+
type PRRApproval struct {
36+
Number string `json:"kep-number" yaml:"kep-number"`
37+
Alpha PRRMilestone `json:"alpha" yaml:"alpha,omitempty"`
38+
Beta PRRMilestone `json:"beta" yaml:"beta,omitempty"`
39+
Stable PRRMilestone `json:"stable" yaml:"stable,omitempty"`
40+
41+
// TODO(api): Move to separate struct for handling document parsing
42+
Error error `json:"-" yaml:"-"`
43+
}
44+
45+
func (prr *PRRApproval) Validate() error {
46+
v := validator.New()
47+
if err := v.Struct(prr); err != nil {
48+
return errors.Wrap(err, "running validation")
49+
}
50+
51+
return nil
52+
}
53+
54+
func (prr *PRRApproval) ApproverForStage(stage string) string {
55+
switch stage {
56+
case "alpha":
57+
return prr.Alpha.Approver
58+
case "beta":
59+
return prr.Beta.Approver
60+
case "stable":
61+
return prr.Stable.Approver
62+
}
63+
64+
return ""
65+
}
66+
67+
// TODO(api): Can we refactor the proposal `Milestone` to retrieve this?
68+
type PRRMilestone struct {
69+
Approver string `json:"approver" yaml:"approver"`
70+
}
71+
72+
type PRRHandler Parser
73+
74+
// TODO(api): Make this a generic parser for all `Document` types
75+
func (p *PRRHandler) Parse(in io.Reader) (*PRRApproval, error) {
76+
scanner := bufio.NewScanner(in)
77+
var body bytes.Buffer
78+
for scanner.Scan() {
79+
line := scanner.Text() + "\n"
80+
body.WriteString(line)
81+
}
82+
83+
approval := &PRRApproval{}
84+
if err := scanner.Err(); err != nil {
85+
return approval, errors.Wrap(err, "reading file")
86+
}
87+
88+
if err := yaml.Unmarshal(body.Bytes(), &approval); err != nil {
89+
p.Errors = append(p.Errors, errors.Wrap(err, "error unmarshalling YAML"))
90+
return approval, errors.Wrap(err, "unmarshalling YAML")
91+
}
92+
93+
if valErr := approval.Validate(); valErr != nil {
94+
p.Errors = append(p.Errors, errors.Wrap(valErr, "validating PRR"))
95+
return approval, errors.Wrap(valErr, "validating PRR")
96+
}
97+
98+
return approval, nil
99+
}
Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2020 The Kubernetes Authors.
2+
Copyright 2021 The Kubernetes Authors.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -14,18 +14,28 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package main
17+
package api
1818

1919
import (
20-
flag "github.com/spf13/pflag"
21-
22-
"k8s.io/enhancements/pkg/kepctl"
20+
"io"
2321
)
2422

25-
func addRepoPathFlag(
26-
f *flag.FlagSet,
27-
opts *kepctl.CommonArgs,
28-
) {
29-
f.StringVar(&opts.RepoPath, "repo-path", "", "Path to kubernetes/enhancements")
30-
f.StringVar(&opts.TokenPath, "gh-token-path", "", "Path to a file with a GitHub API token")
23+
// TODO(api): Populate interface
24+
// TODO(api): Mock interface
25+
type File interface {
26+
Parse(io.Reader) (Document, error)
27+
}
28+
29+
// TODO(api): Populate interface
30+
// TODO(api): Mock interface
31+
// Document is an interface satisfied by the following types:
32+
// - `Proposal` (KEP)
33+
// - `PRRApproval`
34+
// - `Receipt` (coming soon)
35+
type Document interface {
36+
Validate() error
37+
}
38+
39+
type Parser struct {
40+
Errors []error
3141
}

api/proposal.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ limitations under the License.
1616

1717
package api
1818

19+
import (
20+
"bufio"
21+
"bytes"
22+
"crypto/md5"
23+
"fmt"
24+
"io"
25+
"strings"
26+
27+
"github.com/go-playground/validator/v10"
28+
"github.com/pkg/errors"
29+
"gopkg.in/yaml.v3"
30+
)
31+
1932
type Proposals []*Proposal
2033

2134
func (p *Proposals) AddProposal(proposal *Proposal) {
@@ -56,6 +69,65 @@ type Proposal struct {
5669
Contents string `json:"markdown" yaml:"-"`
5770
}
5871

72+
func (p *Proposal) Validate() error {
73+
v := validator.New()
74+
if err := v.Struct(p); err != nil {
75+
return errors.Wrap(err, "running validation")
76+
}
77+
78+
return nil
79+
}
80+
81+
type KEPHandler Parser
82+
83+
// TODO(api): Make this a generic parser for all `Document` types
84+
func (k *KEPHandler) Parse(in io.Reader) (*Proposal, error) {
85+
scanner := bufio.NewScanner(in)
86+
count := 0
87+
metadata := []byte{}
88+
var body bytes.Buffer
89+
for scanner.Scan() {
90+
line := scanner.Text() + "\n"
91+
if strings.Contains(line, "---") {
92+
count++
93+
continue
94+
}
95+
if count == 1 {
96+
metadata = append(metadata, []byte(line)...)
97+
} else {
98+
body.WriteString(line)
99+
}
100+
}
101+
102+
kep := &Proposal{
103+
Contents: body.String(),
104+
}
105+
106+
if err := scanner.Err(); err != nil {
107+
return kep, errors.Wrap(err, "reading file")
108+
}
109+
110+
// this file is just the KEP metadata
111+
if count == 0 {
112+
metadata = body.Bytes()
113+
kep.Contents = ""
114+
}
115+
116+
if err := yaml.Unmarshal(metadata, &kep); err != nil {
117+
k.Errors = append(k.Errors, errors.Wrap(err, "error unmarshalling YAML"))
118+
return kep, errors.Wrap(err, "unmarshalling YAML")
119+
}
120+
121+
if valErr := kep.Validate(); valErr != nil {
122+
k.Errors = append(k.Errors, errors.Wrap(valErr, "validating KEP"))
123+
return kep, errors.Wrap(valErr, "validating KEP")
124+
}
125+
126+
kep.ID = hash(kep.OwningSIG + ":" + kep.Title)
127+
128+
return kep, nil
129+
}
130+
59131
type Milestone struct {
60132
Alpha string `json:"alpha" yaml:"alpha"`
61133
Beta string `json:"beta" yaml:"beta"`
@@ -66,3 +138,7 @@ type FeatureGate struct {
66138
Name string `json:"name" yaml:"name"`
67139
Components []string `json:"components" yaml:"components"`
68140
}
141+
142+
func hash(s string) string {
143+
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
144+
}

cmd/kepctl/cmd/create.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
Copyright 2020 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 cmd
18+
19+
import (
20+
"github.com/pkg/errors"
21+
"github.com/spf13/cobra"
22+
23+
"k8s.io/enhancements/pkg/kepctl"
24+
)
25+
26+
// TODO: Struct literal instead?
27+
var createOpts = kepctl.CreateOpts{}
28+
29+
var createCmd = &cobra.Command{
30+
Use: "create [KEP]",
31+
Short: "Create a new KEP",
32+
Long: "Create a new KEP using the current KEP template for the given type",
33+
Example: ` kepctl create sig-architecture/000-mykep`,
34+
SilenceUsage: true,
35+
SilenceErrors: true,
36+
PreRunE: func(cmd *cobra.Command, args []string) error {
37+
return createOpts.Validate(args)
38+
},
39+
RunE: func(*cobra.Command, []string) error {
40+
return runCreate(createOpts)
41+
},
42+
}
43+
44+
func init() {
45+
// TODO: Should these all be global args?
46+
createCmd.PersistentFlags().StringVar(
47+
&createOpts.Title,
48+
"title",
49+
"",
50+
"KEP Title",
51+
)
52+
53+
createCmd.PersistentFlags().StringArrayVar(
54+
&createOpts.Authors,
55+
"authors",
56+
[]string{},
57+
"Authors",
58+
)
59+
60+
createCmd.PersistentFlags().StringArrayVar(
61+
&createOpts.Reviewers,
62+
"reviewers",
63+
[]string{},
64+
"Reviewers",
65+
)
66+
67+
createCmd.PersistentFlags().StringVar(
68+
&createOpts.Type,
69+
"type",
70+
"feature",
71+
"KEP Type",
72+
)
73+
74+
createCmd.PersistentFlags().StringVarP(
75+
&createOpts.State,
76+
"state",
77+
"s",
78+
"provisional",
79+
"KEP State",
80+
)
81+
82+
createCmd.PersistentFlags().StringArrayVar(
83+
&createOpts.SIGS,
84+
"sigs",
85+
[]string{},
86+
"Participating SIGs",
87+
)
88+
89+
createCmd.PersistentFlags().StringArrayVar(
90+
&createOpts.PRRApprovers,
91+
"prr-approver",
92+
[]string{},
93+
"PRR Approver",
94+
)
95+
96+
rootCmd.AddCommand(createCmd)
97+
}
98+
99+
func runCreate(createOpts kepctl.CreateOpts) error {
100+
k, err := kepctl.New(createOpts.RepoPath)
101+
if err != nil {
102+
return errors.Wrap(err, "creating kepctl client")
103+
}
104+
105+
return k.Create(&createOpts)
106+
}

0 commit comments

Comments
 (0)