Skip to content

Commit

Permalink
Revert "Merge pull request kubernetes#2425 from justaugustus/refactor…
Browse files Browse the repository at this point in the history
…-revert"

This reverts commit 3e2c87b, reversing
changes made to 0a495c8.
  • Loading branch information
justaugustus committed Feb 10, 2021
1 parent fd90bcb commit 212a652
Show file tree
Hide file tree
Showing 34 changed files with 869 additions and 375 deletions.
99 changes: 99 additions & 0 deletions api/approval.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package api

import (
"bufio"
"bytes"
"io"

"github.com/go-playground/validator/v10"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)

type PRRApprovals []*PRRApproval

func (p *PRRApprovals) AddPRRApproval(prrApproval *PRRApproval) {
*p = append(*p, prrApproval)
}

type PRRApproval struct {
Number string `json:"kep-number" yaml:"kep-number"`
Alpha PRRMilestone `json:"alpha" yaml:"alpha,omitempty"`
Beta PRRMilestone `json:"beta" yaml:"beta,omitempty"`
Stable PRRMilestone `json:"stable" yaml:"stable,omitempty"`

// TODO(api): Move to separate struct for handling document parsing
Error error `json:"-" yaml:"-"`
}

func (prr *PRRApproval) Validate() error {
v := validator.New()
if err := v.Struct(prr); err != nil {
return errors.Wrap(err, "running validation")
}

return nil
}

func (prr *PRRApproval) ApproverForStage(stage string) string {
switch stage {
case "alpha":
return prr.Alpha.Approver
case "beta":
return prr.Beta.Approver
case "stable":
return prr.Stable.Approver
}

return ""
}

// TODO(api): Can we refactor the proposal `Milestone` to retrieve this?
type PRRMilestone struct {
Approver string `json:"approver" yaml:"approver"`
}

type PRRHandler Parser

// TODO(api): Make this a generic parser for all `Document` types
func (p *PRRHandler) Parse(in io.Reader) (*PRRApproval, error) {
scanner := bufio.NewScanner(in)
var body bytes.Buffer
for scanner.Scan() {
line := scanner.Text() + "\n"
body.WriteString(line)
}

approval := &PRRApproval{}
if err := scanner.Err(); err != nil {
return approval, errors.Wrap(err, "reading file")
}

if err := yaml.Unmarshal(body.Bytes(), &approval); err != nil {
p.Errors = append(p.Errors, errors.Wrap(err, "error unmarshalling YAML"))
return approval, errors.Wrap(err, "unmarshalling YAML")
}

if valErr := approval.Validate(); valErr != nil {
p.Errors = append(p.Errors, errors.Wrap(valErr, "validating PRR"))
return approval, errors.Wrap(valErr, "validating PRR")
}

return approval, nil
}
32 changes: 21 additions & 11 deletions cmd/kepctl/helper.go → api/document.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020 The Kubernetes Authors.
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -14,18 +14,28 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package main
package api

import (
flag "github.com/spf13/pflag"

"k8s.io/enhancements/pkg/kepctl"
"io"
)

func addRepoPathFlag(
f *flag.FlagSet,
opts *kepctl.CommonArgs,
) {
f.StringVar(&opts.RepoPath, "repo-path", "", "Path to kubernetes/enhancements")
f.StringVar(&opts.TokenPath, "gh-token-path", "", "Path to a file with a GitHub API token")
// TODO(api): Populate interface
// TODO(api): Mock interface
type File interface {
Parse(io.Reader) (Document, error)
}

// TODO(api): Populate interface
// TODO(api): Mock interface
// Document is an interface satisfied by the following types:
// - `Proposal` (KEP)
// - `PRRApproval`
// - `Receipt` (coming soon)
type Document interface {
Validate() error
}

type Parser struct {
Errors []error
}
76 changes: 76 additions & 0 deletions api/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ limitations under the License.

package api

import (
"bufio"
"bytes"
"crypto/md5"
"fmt"
"io"
"strings"

"github.com/go-playground/validator/v10"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)

type Proposals []*Proposal

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

func (p *Proposal) Validate() error {
v := validator.New()
if err := v.Struct(p); err != nil {
return errors.Wrap(err, "running validation")
}

return nil
}

type KEPHandler Parser

// TODO(api): Make this a generic parser for all `Document` types
func (k *KEPHandler) Parse(in io.Reader) (*Proposal, error) {
scanner := bufio.NewScanner(in)
count := 0
metadata := []byte{}
var body bytes.Buffer
for scanner.Scan() {
line := scanner.Text() + "\n"
if strings.Contains(line, "---") {
count++
continue
}
if count == 1 {
metadata = append(metadata, []byte(line)...)
} else {
body.WriteString(line)
}
}

kep := &Proposal{
Contents: body.String(),
}

if err := scanner.Err(); err != nil {
return kep, errors.Wrap(err, "reading file")
}

// this file is just the KEP metadata
if count == 0 {
metadata = body.Bytes()
kep.Contents = ""
}

if err := yaml.Unmarshal(metadata, &kep); err != nil {
k.Errors = append(k.Errors, errors.Wrap(err, "error unmarshalling YAML"))
return kep, errors.Wrap(err, "unmarshalling YAML")
}

if valErr := kep.Validate(); valErr != nil {
k.Errors = append(k.Errors, errors.Wrap(valErr, "validating KEP"))
return kep, errors.Wrap(valErr, "validating KEP")
}

kep.ID = hash(kep.OwningSIG + ":" + kep.Title)

return kep, nil
}

type Milestone struct {
Alpha string `json:"alpha" yaml:"alpha"`
Beta string `json:"beta" yaml:"beta"`
Expand All @@ -66,3 +138,7 @@ type FeatureGate struct {
Name string `json:"name" yaml:"name"`
Components []string `json:"components" yaml:"components"`
}

func hash(s string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
106 changes: 106 additions & 0 deletions cmd/kepctl/cmd/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cmd

import (
"github.com/pkg/errors"
"github.com/spf13/cobra"

"k8s.io/enhancements/pkg/kepctl"
)

// TODO: Struct literal instead?
var createOpts = kepctl.CreateOpts{}

var createCmd = &cobra.Command{
Use: "create [KEP]",
Short: "Create a new KEP",
Long: "Create a new KEP using the current KEP template for the given type",
Example: ` kepctl create sig-architecture/000-mykep`,
SilenceUsage: true,
SilenceErrors: true,
PreRunE: func(cmd *cobra.Command, args []string) error {
return createOpts.Validate(args)
},
RunE: func(*cobra.Command, []string) error {
return runCreate(createOpts)
},
}

func init() {
// TODO: Should these all be global args?
createCmd.PersistentFlags().StringVar(
&createOpts.Title,
"title",
"",
"KEP Title",
)

createCmd.PersistentFlags().StringArrayVar(
&createOpts.Authors,
"authors",
[]string{},
"Authors",
)

createCmd.PersistentFlags().StringArrayVar(
&createOpts.Reviewers,
"reviewers",
[]string{},
"Reviewers",
)

createCmd.PersistentFlags().StringVar(
&createOpts.Type,
"type",
"feature",
"KEP Type",
)

createCmd.PersistentFlags().StringVarP(
&createOpts.State,
"state",
"s",
"provisional",
"KEP State",
)

createCmd.PersistentFlags().StringArrayVar(
&createOpts.SIGS,
"sigs",
[]string{},
"Participating SIGs",
)

createCmd.PersistentFlags().StringArrayVar(
&createOpts.PRRApprovers,
"prr-approver",
[]string{},
"PRR Approver",
)

rootCmd.AddCommand(createCmd)
}

func runCreate(createOpts kepctl.CreateOpts) error {
k, err := kepctl.New(createOpts.RepoPath)
if err != nil {
return errors.Wrap(err, "creating kepctl client")
}

return k.Create(&createOpts)
}
Loading

0 comments on commit 212a652

Please sign in to comment.