Skip to content

👻 ff release-0.2 branch to master #475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Jun 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7499995
:running: support release notes on new version
DirectXMan12 Apr 22, 2019
52f4a7c
Fix docs & comments referring to "Reconciler" instead of "reconcile"
luksa May 17, 2019
2d952ac
webhook: Handle TLS certificate rotation
bison May 20, 2019
96b67f2
Merge pull request #421 from bison/tls-reload
k8s-ci-robot May 20, 2019
d79d6ae
update contributing.md
anthonyho007 May 21, 2019
d850185
:sparkles: webhook server doesn't use leader election by default
May 24, 2019
e381b18
Merge pull request #441 from mengqiy/webhook_le
k8s-ci-robot May 24, 2019
0af7a98
:bug: set status in conversion response
May 24, 2019
e72b0e7
Merge pull request #434 from luksa/fix_docs
k8s-ci-robot May 24, 2019
13ee2bc
Merge pull request #443 from mengqiy/conversionstatus
k8s-ci-robot May 24, 2019
1da1a4b
Merge pull request #438 from anthonyho007/fix-contribute.md
k8s-ci-robot May 29, 2019
761e03e
update internal controller for more clean code and metrics
adohe May 30, 2019
31d8c66
:sparkles: Allow setting "UseExistingCluster" via environment
adohe May 30, 2019
0532336
Merge pull request #448 from adohe/update_internal_controller
k8s-ci-robot May 30, 2019
5320b25
Merge pull request #449 from adohe/support_use_existing_cluster
k8s-ci-robot May 30, 2019
2a14111
Allow setting controller name, fix default
DirectXMan12 May 30, 2019
b56d269
Merge pull request #458 from DirectXMan12/bug/metrics-compatible-defa…
k8s-ci-robot May 30, 2019
267523b
:sparkles: more visibility of the testing control plane
May 30, 2019
228ca93
Merge pull request #404 from DirectXMan12/infra/release-notes-cross-v…
k8s-ci-robot May 31, 2019
bce1e17
Merge pull request #459 from mengqiy/controlplanevisibility
k8s-ci-robot May 31, 2019
596620d
:ghost: add webhook markers in the example
May 31, 2019
b88347b
Merge pull request #462 from mengqiy/addmarkers
k8s-ci-robot Jun 4, 2019
55c40b7
:running: use :ghost: for no release note commits
Jun 4, 2019
96826f6
🐛 Fix race when adding runnable
abursavich Jun 4, 2019
aa16141
Merge pull request #465 from mengqiy/ghost
k8s-ci-robot Jun 5, 2019
17e0976
Verify Emoji with GH actions
DirectXMan12 Jun 5, 2019
cd4692d
Merge pull request #474 from DirectXMan12/infra/verify-emoji
k8s-ci-robot Jun 6, 2019
be010e1
Merge pull request #466 from abursavich/dontpanic
k8s-ci-robot Jun 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/main.workflow
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
workflow "PR Checks" {
on = "pull_request"
resolves = ["verify-emoji"]
}

action "verify-emoji" {
uses = "./hack/release"
secrets = ["GITHUB_TOKEN"]
}
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ Please see https://git.k8s.io/community/CLA.md for more info
1. Setup tools
```bash
$ go get -u github.com/golang/dep/cmd/dep
$ go get -u gopkg.in/alecthomas/gometalinter.v2
$ gometalinter.v2 --install # if can't load package, refer: https://github.com/alecthomas/gometalinter/issues/404
$ curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.15.0
```
1. Test
```bash
TRACE=1 ./hack/check-everything.sh
GO111MODULE=on TRACE=1 ./hack/check-everything.sh
```

1 change: 1 addition & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions VERSIONING.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ a:
- Patch fix: :bug: (`:bug:`)
- Docs: :book: (`:book:`)
- Infra/Tests/Other: :running: (`:running:`)
- No release note: :ghost: (`:ghost:`)

Use :ghost: (no release note) only for the PRs that change or revert unreleased
changes, which don't deserve a release note. Please don't abuse it.

You can also use the equivalent emoji directly, since GitHub doesn't
render the `:xyz:` aliases in PR titles.
Expand Down
2 changes: 1 addition & 1 deletion examples/builtins/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func main() {
os.Exit(1)
}

// Setup a new controller to Reconciler ReplicaSets
// Setup a new controller to reconcile ReplicaSets
entryLog.Info("Setting up controller")
c, err := controller.New("foo-controller", mgr, controller.Options{
Reconciler: &reconcileReplicaSet{client: mgr.GetClient(), log: log.WithName("reconciler")},
Expand Down
6 changes: 6 additions & 0 deletions examples/crd/pkg/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ type ChaosPodList struct {
Items []ChaosPod `json:"items"`
}

// +kubebuilder:webhook:failurePolicy=fail,groups=chaosapps.metamagical.io,resources=chaospods,verbs=create;update,versions=v1,name=vchaospod.kb.io,path=/validate-chaosapps-metamagical-io-v1-chaospod,mutating=false

var _ webhook.Validator = &ChaosPod{}

// ValidateCreate implements webhookutil.validator so a webhook will be registered for the type
func (c *ChaosPod) ValidateCreate() error {
log.Info("validate create", "name", c.Name)
Expand Down Expand Up @@ -89,6 +93,8 @@ func (c *ChaosPod) ValidateUpdate(old runtime.Object) error {
return nil
}

// +kubebuilder:webhook:failurePolicy=fail,groups=chaosapps.metamagical.io,resources=chaospods,verbs=create;update,versions=v1,name=mchaospod.kb.io,path=/mutate-chaosapps-metamagical-io-v1-chaospod,mutating=true

var _ webhook.Defaulter = &ChaosPod{}

// Default implements webhookutil.defaulter so a webhook will be registered for the type
Expand Down
13 changes: 13 additions & 0 deletions hack/release/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM k8s.gcr.io/debian-base:v1.0.0

LABEL com.github.actions.name="KubeBuilder PR Emoji"
LABEL com.github.actions.name="Verify that KubeBuilder release notes emoji are present on the PR"
LABEL com.github.actions.icon="git-pull-request"
LABEL com.github.actions.color="blue"

RUN apt-get update -y && apt-get install -y bash jq curl

COPY common.sh /common.sh
COPY verify-emoji.sh /verify-emoji.sh

ENTRYPOINT ["/verify-emoji.sh"]
82 changes: 67 additions & 15 deletions hack/release/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ cr_major_pattern=":warning:|$(printf "\xe2\x9a\xa0")"
cr_minor_pattern=":sparkles:|$(printf "\xe2\x9c\xa8")"
cr_patch_pattern=":bug:|$(printf "\xf0\x9f\x90\x9b")"
cr_docs_pattern=":book:|$(printf "\xf0\x9f\x93\x96")"
cr_no_release_note_pattern=":ghost:|$(printf "\xf0\x9f\x91\xbb")"
cr_other_pattern=":running:|$(printf "\xf0\x9f\x8f\x83")"
cr_all_pattern="${cr_major_pattern}|${cr_minor_pattern}|${cr_patch_pattern}|${cr_docs_pattern}|${cr_other_pattern}"

# cr::symbol-type-raw turns :xyz: and the corresponding emoji
# into one of "major", "minor", "patch", "docs", "other", or
Expand All @@ -24,6 +26,9 @@ cr::symbol-type-raw() {
@(${cr_docs_pattern})?('!'))
echo "docs"
;;
@(${cr_no_release_note_pattern})?('!'))
echo "no_release_note"
;;
@(${cr_other_pattern})?('!'))
echo "other"
;;
Expand Down Expand Up @@ -66,6 +71,52 @@ git::ensure-release-branch() {
fi
}

# git::export-version-from-branch outputs the current version
# for the given branch (as the argument) as exported variables
# (${maj,min,patch}_ver, last_tag).
git::export-version-from-branch() {
local target_branch=${1?must specify a branch}
local current_branch=$(git branch --show-current -q)

local expected_maj_ver
local expected_min_ver
if [[ ${target_branch} =~ release-0.([[:digit:]]+) ]]; then
expected_maj_ver=0
expected_min_ver=${BASH_REMATCH[1]}
elif [[ ${target_branch} =~ release-([[:digit:]]+) ]]; then
expected_maj_ver=${BASH_REMATCH[1]}
else
echo "branch ${target_branch} does not appear to be for a release -- it should be release-X or release-0.Y" >&2
exit 1
fi

local tag_pattern='v([[:digit:]]+).([[:digit:]]+).([[:digit:]]+)'

git checkout -q ${target_branch}

# make sure we've got a tag that matches *some* release
last_tag=$(git describe --tags --abbrev=0) # try to fetch just the "current" tag name
if [[ ! ${last_tag} =~ ${tag_pattern} ]]; then
# it's probably for a previous version
echo "tag ${last_tag} does not appear to be for a release -- it should be vX.Y.Z" >&2
git checkout -q ${current_branch}
exit 1
fi

export min_ver=${BASH_REMATCH[2]}
export patch_ver=${BASH_REMATCH[3]}
export maj_ver=${BASH_REMATCH[1]}
export last_tag=${last_tag}

if ${2:-1} && ([[ ${maj_ver} != ${expected_maj_ver} ]] || [[ ${maj_ver} == 0 && ${min_ver} != ${expected_min_ver} ]]); then
echo "tag ${last_tag} does not appear to be for a the right release (${target_branch})" >&2
git checkout ${current_branch}
exit 1
fi

git checkout -q ${current_branch}
}

# git::export-current-version outputs the current version
# as exported variables (${maj,min,patch}_ver, last_tag) after
# checking that we're on the right release branch.
Expand All @@ -75,25 +126,26 @@ git::export-current-version() {

# deal with the release-0.1 branch, or similar
local release_ver=${BASH_REMATCH[1]}
maj_ver=${release_ver}
local tag_pattern='v${maj_ver}.([[:digit:]]+).([[:digit]]+)'
if [[ ${maj_ver} =~ 0\.([[:digit:]]+) ]]; then
maj_ver=0
min_ver=${BASH_REMATCH[1]}
local tag_pattern="v0.(${min_ver}).([[:digit:]]+)"
local expected_maj_ver=${release_ver}
if [[ ${expected_maj_ver} =~ 0\.([[:digit:]]+) ]]; then
expected_maj_ver=0
local expected_min_ver=${BASH_REMATCH[1]}
fi

# make sure we've got a tag that matches our release branch
last_tag=$(git describe --tags --abbrev=0) # try to fetch just the "current" tag name
if [[ ! ${last_tag} =~ ${tag_pattern} ]]; then
echo "tag ${last_tag} does not appear to be a release for this release (${release_ver})-- it should be v${maj_ver}.Y.Z" >&2
exit 1
git::export-version-from-branch "release-${release_ver}" false

local last_tag_branch=""
if [[ ${maj_ver} == "0" && ${min_ver} -eq $((expected_min_ver-1)) ]]; then
echo "most recent tag is a release behind (${last_tag}), checking previous release branch to be safe" >&2
last_tag_branch="release-0.${min_ver}"
elif [[ ${maj_ver} -eq $((expected_maj_ver-1)) ]]; then
echo "most recent tag is a release behind (${last_tag}), checking previous release branch to be safe" >&2
last_tag_branch="release-${maj_ver}"
fi

export min_ver=${BASH_REMATCH[1]}
export patch_ver=${BASH_REMATCH[2]}
export maj_ver=${maj_ver}
export last_tag=${last_tag}
if [[ -n "${last_tag_branch}" ]]; then
git::export-version-from-branch ${last_tag_branch} true
fi
}

# git::next-version figures out the next version to tag
Expand Down
6 changes: 3 additions & 3 deletions hack/release/release-notes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ while read commit_word commit; do
patch)
bugfixes="${bugfixes}- ${pr_title} (#${pr_number})${NEWLINE}"
;;
docs|other)
docs|no_release_note|other)
# skip non-code-changes
;;
unknown)
Expand All @@ -64,8 +64,8 @@ done <<<$(git rev-list ${last_tag}..HEAD --merges --pretty=format:%B)

# TODO: sort non merge commits with tags

[[ -n "${breaking}" ]] && printf '\e[1;31mbreaking changes this version\e[0m' >&2
[[ -n "${unknown}" ]] && printf '\e[1;35munknown changes in this release -- categorize manually\e[0m' >&2
[[ -n "${breaking}" ]] && printf '\e[1;31mbreaking changes this version\e[0m\n' >&2
[[ -n "${unknown}" ]] && printf '\e[1;35munknown changes in this release -- categorize manually\e[0m\n' >&2

echo "" >&2
echo "" >&2
Expand Down
29 changes: 29 additions & 0 deletions hack/release/verify-emoji.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

set -eu
set -o pipefail

pr_title=$(jq -r '.pull_request.title' < ${GITHUB_EVENT_PATH})

read pr_prefix rest <<<${pr_title}

source "$(dirname ${BASH_SOURCE})/common.sh"

pr_type=$(cr::symbol-type ${pr_prefix})

summary=""
conclusion="success"
if [[ ${pr_type} == "unknown" ]]; then
summary="You must specify an emoji at the beginning of the PR to indicate what kind of change this is.\nValid emoji: ${cr_all_pattern}.\nYou specified '${pr_prefix}'.\nSee VERSIONING.md for more information."
conclusion="failure"
else
summary="PR is a ${pr_type} change (${pr_prefix})."
fi

# get the PR (the PR sent from the event has the base branch head as the head)
base_link=$(jq -r '.pull_request.url' < ${GITHUB_EVENT_PATH})
head_commit=$(curl -H "Authorization: Bearer ${GITHUB_TOKEN}" -H 'Accept: application/vnd.github.antiope-preview+json' -q ${base_link} | jq -r '.head.sha')
echo "head commit is ${head_commit}"

curl https://api.github.com/repos/${GITHUB_REPOSITORY}/check-runs -XPOST -H "Authorization: Bearer ${GITHUB_TOKEN}" -H 'Accept: application/vnd.github.antiope-preview+json' -H 'Content-Type: application/json' -q --data-raw '{"name": "Verify Emoji", "head_sha": "'${head_commit}'", "conclusion": "'${conclusion}'", "status": "completed", "completed_at": "'$(date -Iseconds)'", "output": {"title": "Verify Emoji", "summary": "'"${summary}"'"}}'

17 changes: 15 additions & 2 deletions pkg/builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Builder struct {
watchRequest []watchRequest
config *rest.Config
ctrl controller.Controller
name string
}

// SimpleController returns a new Builder.
Expand Down Expand Up @@ -131,6 +132,16 @@ func (blder *Builder) WithEventFilter(p predicate.Predicate) *Builder {
return blder
}

// Named sets the name of the controller to the given name. The name shows up
// in metrics, among other things, and thus should be a prometheus compatible name
// (underscores and alphanumeric characters only).
//
// By default, controllers are named using the lowercase version of their kind.
func (blder *Builder) Named(name string) *Builder {
blder.name = name
return blder
}

// Complete builds the Application ControllerManagedBy.
func (blder *Builder) Complete(r reconcile.Reconciler) error {
_, err := blder.Build(r)
Expand Down Expand Up @@ -227,12 +238,14 @@ func (blder *Builder) doManager() error {
}

func (blder *Builder) getControllerName() (string, error) {
if blder.name != "" {
return blder.name, nil
}
gvk, err := getGvk(blder.apiType, blder.mgr.GetScheme())
if err != nil {
return "", err
}
name := fmt.Sprintf("%s-application", strings.ToLower(gvk.Kind))
return name, nil
return strings.ToLower(gvk.Kind), nil
}

func (blder *Builder) doController(r reconcile.Reconciler) error {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type Options struct {
// Work typically is reads and writes Kubernetes objects to make the system state match the state specified
// in the object Spec.
type Controller interface {
// Reconciler is called to Reconciler an object by Namespace/Name
// Reconciler is called to reconcile an object by Namespace/Name
reconcile.Reconciler

// Watch takes events provided by a Source and uses the EventHandler to
Expand Down
26 changes: 13 additions & 13 deletions pkg/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ clients, caches, schemes, etc. Controllers should be Started through the Manage
Controller

Controller implements a Kubernetes API by responding to events (object Create, Update, Delete) and ensuring that
the state specified in the Spec of the object matches the state of the system. This is called a Reconciler.
the state specified in the Spec of the object matches the state of the system. This is called a reconcile.
If they do not match, the Controller will create / update / delete objects as needed to make them match.

Controllers are implemented as worker queues that process reconcile.Requests (requests to Reconciler the
Controllers are implemented as worker queues that process reconcile.Requests (requests to reconcile the
state for a specific object).

Unlike http handlers, Controllers DO NOT handle events directly, but enqueue Requests to eventually Reconciler
Unlike http handlers, Controllers DO NOT handle events directly, but enqueue Requests to eventually reconcile
the object. This means the handling of multiple events may be batched together and the full state of the
system must be read for each Reconciler.
system must be read for each reconcile.

* Controllers require a Reconciler to be provided to perform the work pulled from the work queue.

Expand All @@ -65,11 +65,11 @@ Validating webhook is used to validate if an object meets certain requirements.
Reconciler

Reconciler is a function provided to a Controller that may be called at anytime with the Name and Namespace of an object.
When called, Reconciler will ensure that the state of the system matches what is specified in the object at the
time Reconciler is called.
When called, the Reconciler will ensure that the state of the system matches what is specified in the object at the
time the Reconciler is called.

Example: Reconciler invoked for a ReplicaSet object. The ReplicaSet specifies 5 replicas but only
3 Pods exist in the system. Reconciler creates 2 more Pods and sets their OwnerReference to point at the
3 Pods exist in the system. The Reconciler creates 2 more Pods and sets their OwnerReference to point at the
ReplicaSet with controller=true.

* Reconciler contains all of the business logic of a Controller.
Expand All @@ -80,7 +80,7 @@ a mapping (e.g. owner references) that maps the object that triggers the reconci

* Reconciler is provided the Name / Namespace of the object to reconcile.

* Reconciler does not care about the event contents or event type responsible for triggering the Reconciler.
* Reconciler does not care about the event contents or event type responsible for triggering the reconcile.
- e.g. it doesn't matter whether a ReplicaSet was created or updated, Reconciler will always compare the number of
Pods in the system against what is specified in the object at the time it is called.

Expand Down Expand Up @@ -159,7 +159,7 @@ Controller Example
1.2 Pod (created by ReplicaSet) -> handler.EnqueueRequestForOwnerHandler - enqueue a Request with the
Owning ReplicaSet Namespace and Name.

2. Reconciler ReplicaSet in response to an event
2. reconcile ReplicaSet in response to an event

2.1 ReplicaSet object created -> Read ReplicaSet, try to read Pods -> if is missing create Pods.

Expand All @@ -169,7 +169,7 @@ Owning ReplicaSet Namespace and Name.

Watching and EventHandling

Controllers may Watch multiple Kinds of objects (e.g. Pods, ReplicaSets and Deployments), but they Reconciler
Controllers may Watch multiple Kinds of objects (e.g. Pods, ReplicaSets and Deployments), but they reconcile
only a single Type. When one Type of object must be updated in response to changes in another Type of object,
an EnqueueRequestFromMapFunc may be used to map events from one type to another. e.g. Respond to a cluster resize
event (add / delete Node) by re-reconciling all instances of some API.
Expand All @@ -189,10 +189,10 @@ Controller Writing Tips

Reconciler Runtime Complexity:

* It is better to write Controllers to perform an O(1) Reconciler N times (e.g. on N different objects) instead of
performing an O(N) Reconciler 1 time (e.g. on a single object which manages N other objects).
* It is better to write Controllers to perform an O(1) reconcile N times (e.g. on N different objects) instead of
performing an O(N) reconcile 1 time (e.g. on a single object which manages N other objects).

* Example: If you need to update all Services in response to a Node being added - Reconciler Services but Watch
* Example: If you need to update all Services in response to a Node being added - reconcile Services but Watch
Nodes (transformed to Service object name / Namespaces) instead of Reconciling Nodes and updating Services

Event Multiplexing:
Expand Down
Loading