Skip to content
This repository has been archived by the owner on May 3, 2022. It is now read-only.

Introduce fleet summary report in Capacity Target #69

Merged
merged 31 commits into from
Mar 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
68b2ac5
capacity controller: include reporting in capacity target
Dec 27, 2018
54f12db
capacity controller: aggregate container states per state in report
Dec 27, 2018
e7f066a
capacity controller: add tests for releases with single and multiple …
Feb 11, 2019
e437039
hack/update-codegen.sh
Feb 11, 2019
bc0b8c6
reporting: make linter happy and clean up
Feb 12, 2019
7dc41b6
reporting: better error message
Feb 12, 2019
06436a2
reporting: propagate cluster name for proper keying
Feb 12, 2019
dfeadb3
reporting: capacity target returns correct report with multiple pods …
Feb 12, 2019
79e2fc2
reporting: make complex test case more realistic
Feb 12, 2019
f772c6e
reporting: move sorting to another method
Feb 12, 2019
81ae4a5
reporting: create builders to aid testing
Feb 13, 2019
1fe2274
reporting: use builders when constructing report
Feb 13, 2019
5114001
report: clean up
Feb 14, 2019
378658a
report: move types around
Feb 14, 2019
c560018
report: clean up, use builder everywhere
Feb 14, 2019
e751233
report: remove unused method
Feb 14, 2019
2d0781b
report: move breakdown building and sorting to a method
Feb 14, 2019
6c79aff
report: make linter happy
Feb 14, 2019
034c2a5
report: make linter happy
Feb 14, 2019
a5786d1
report: add test cases for report builder
Feb 19, 2019
e242cba
report: use same function to compute pod condition breakdown keys
Feb 20, 2019
7c4684f
report: chain increment count call to make it more fluid
Feb 20, 2019
5dc709f
report: organize import order
Feb 20, 2019
313da57
report: organize import order
Feb 20, 2019
d1a28d6
report: organize import order and add import aliases
Feb 20, 2019
b8903df
report: add import aliases
Feb 20, 2019
717abb5
report: organize import order and add import aliases
Feb 20, 2019
e8f179b
report: add container breakdown example message
Feb 20, 2019
7d258b0
hack/update-codegen.sh
Feb 22, 2019
a71ccdf
reporting: remove unused field
Feb 22, 2019
3af17cb
Removed the `initialCount` from `AddContainerState`, and renamed the
parhamdoustdar Mar 11, 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
35 changes: 35 additions & 0 deletions pkg/apis/shipper/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,47 @@ type CapacityTargetStatus struct {
Clusters []ClusterCapacityStatus `json:"clusters,omitempty"`
}

type ClusterCapacityReportContainerBreakdownExample struct {
Pod string `json:"pod"`
Message *string `json:"message,omitempty"`
}

type ClusterCapacityReportContainerStateBreakdown struct {
Count uint32 `json:"count"`
Example ClusterCapacityReportContainerBreakdownExample `json:"example"`
Reason string `json:"reason,omitempty"`
Type string `json:"type"`
}

type ClusterCapacityReportContainerBreakdown struct {
Name string `json:"name"`
States []ClusterCapacityReportContainerStateBreakdown `json:"states"`
}

type ClusterCapacityReportBreakdown struct {
Containers []ClusterCapacityReportContainerBreakdown `json:"containers,omitempty"`
Count uint32 `json:"count"`
Reason string `json:"reason,omitempty"`
Status string `json:"status"`
Type string `json:"type"`
}

type ClusterCapacityReportOwner struct {
Name string `json:"name"`
}

type ClusterCapacityReport struct {
Owner ClusterCapacityReportOwner `json:"owner"`
Breakdown []ClusterCapacityReportBreakdown `json:"breakdown,omitempty"`
}

type ClusterCapacityStatus struct {
Name string `json:"name"`
AvailableReplicas int32 `json:"availableReplicas"`
AchievedPercent int32 `json:"achievedPercent"`
SadPods []PodStatus `json:"sadPods,omitempty"`
Conditions []ClusterCapacityCondition `json:"conditions,omitempty"`
Reports []ClusterCapacityReport `json:"reports,omitempty"`
}

type ClusterConditionType string
Expand Down
135 changes: 135 additions & 0 deletions pkg/apis/shipper/v1alpha1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,134 @@ func (in *ClusterCapacityCondition) DeepCopy() *ClusterCapacityCondition {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityReport) DeepCopyInto(out *ClusterCapacityReport) {
*out = *in
out.Owner = in.Owner
if in.Breakdown != nil {
in, out := &in.Breakdown, &out.Breakdown
*out = make([]ClusterCapacityReportBreakdown, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCapacityReport.
func (in *ClusterCapacityReport) DeepCopy() *ClusterCapacityReport {
if in == nil {
return nil
}
out := new(ClusterCapacityReport)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityReportBreakdown) DeepCopyInto(out *ClusterCapacityReportBreakdown) {
*out = *in
if in.Containers != nil {
in, out := &in.Containers, &out.Containers
*out = make([]ClusterCapacityReportContainerBreakdown, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCapacityReportBreakdown.
func (in *ClusterCapacityReportBreakdown) DeepCopy() *ClusterCapacityReportBreakdown {
if in == nil {
return nil
}
out := new(ClusterCapacityReportBreakdown)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityReportContainerBreakdown) DeepCopyInto(out *ClusterCapacityReportContainerBreakdown) {
*out = *in
if in.States != nil {
in, out := &in.States, &out.States
*out = make([]ClusterCapacityReportContainerStateBreakdown, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCapacityReportContainerBreakdown.
func (in *ClusterCapacityReportContainerBreakdown) DeepCopy() *ClusterCapacityReportContainerBreakdown {
if in == nil {
return nil
}
out := new(ClusterCapacityReportContainerBreakdown)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityReportContainerBreakdownExample) DeepCopyInto(out *ClusterCapacityReportContainerBreakdownExample) {
*out = *in
if in.Message != nil {
in, out := &in.Message, &out.Message
if *in == nil {
*out = nil
} else {
*out = new(string)
**out = **in
}
}
return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCapacityReportContainerBreakdownExample.
func (in *ClusterCapacityReportContainerBreakdownExample) DeepCopy() *ClusterCapacityReportContainerBreakdownExample {
if in == nil {
return nil
}
out := new(ClusterCapacityReportContainerBreakdownExample)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityReportContainerStateBreakdown) DeepCopyInto(out *ClusterCapacityReportContainerStateBreakdown) {
*out = *in
in.Example.DeepCopyInto(&out.Example)
return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCapacityReportContainerStateBreakdown.
func (in *ClusterCapacityReportContainerStateBreakdown) DeepCopy() *ClusterCapacityReportContainerStateBreakdown {
if in == nil {
return nil
}
out := new(ClusterCapacityReportContainerStateBreakdown)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityReportOwner) DeepCopyInto(out *ClusterCapacityReportOwner) {
*out = *in
return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCapacityReportOwner.
func (in *ClusterCapacityReportOwner) DeepCopy() *ClusterCapacityReportOwner {
if in == nil {
return nil
}
out := new(ClusterCapacityReportOwner)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterCapacityStatus) DeepCopyInto(out *ClusterCapacityStatus) {
*out = *in
Expand All @@ -361,6 +489,13 @@ func (in *ClusterCapacityStatus) DeepCopyInto(out *ClusterCapacityStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Reports != nil {
in, out := &in.Reports, &out.Reports
*out = make([]ClusterCapacityReport, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}

Expand Down
65 changes: 65 additions & 0 deletions pkg/controller/capacity/builder/container_breakdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package builder

import (
"sort"

shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1"
)

type ContainerStateBreakdown struct {
containerName string
states []*shipper.ClusterCapacityReportContainerStateBreakdown
}

func NewContainerBreakdown(containerName string) *ContainerStateBreakdown {
return &ContainerStateBreakdown{containerName: containerName}
}

func (c *ContainerStateBreakdown) AddOrIncrementState(
podExampleName string,
containerConditionType string,
containerConditionReason string,
containerExampleMessage string,
) *ContainerStateBreakdown {

var m *string
if len(containerExampleMessage) > 0 {
m = &containerExampleMessage
}

for _, s := range c.states {
if s.Type == containerConditionType && s.Reason == containerConditionReason {
s.Count += 1
return c
}
}

breakdown := shipper.ClusterCapacityReportContainerStateBreakdown{
Count: 1,
Type: containerConditionType,
Reason: containerConditionReason,
Example: shipper.ClusterCapacityReportContainerBreakdownExample{
Pod: podExampleName,
Message: m,
},
}
c.states = append(c.states, &breakdown)
return c
}

func (c *ContainerStateBreakdown) Build() shipper.ClusterCapacityReportContainerBreakdown {
stateCount := len(c.states)
orderedStates := make([]shipper.ClusterCapacityReportContainerStateBreakdown, stateCount)
for i, v := range c.states {
orderedStates[i] = *v
}

sort.Slice(orderedStates, func(i, j int) bool {
return orderedStates[i].Type < orderedStates[j].Type
})

return shipper.ClusterCapacityReportContainerBreakdown{
Name: c.containerName,
States: orderedStates,
}
}
90 changes: 90 additions & 0 deletions pkg/controller/capacity/builder/pod_condition_breakdown.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package builder

import (
"sort"

shipper "github.com/bookingcom/shipper/pkg/apis/shipper/v1alpha1"
)

type containerStateBreakdownBuilders map[string]*ContainerStateBreakdown

func (c containerStateBreakdownBuilders) Get(containerName string) *ContainerStateBreakdown {
var b *ContainerStateBreakdown
var ok bool
if b, ok = c[containerName]; !ok {
b = NewContainerBreakdown(containerName)
c[containerName] = b
}
return b
}

type PodConditionBreakdown struct {
podCount uint32
podConditionType string
podConditionStatus string
podConditionReason string

containerStateBreakdownBuilders containerStateBreakdownBuilders
}

func NewPodConditionBreakdown(
initialPodCount uint32,
podConditionType string,
podConditionStatus string,
podConditionReason string,
) *PodConditionBreakdown {
return &PodConditionBreakdown{
podCount: initialPodCount,
podConditionType: podConditionType,
podConditionStatus: podConditionStatus,
podConditionReason: podConditionReason,
containerStateBreakdownBuilders: make(containerStateBreakdownBuilders),
}
}

func PodConditionBreakdownKey(typ, status, reason string) string {
return typ + status + reason
}

func (p *PodConditionBreakdown) Key() string {
return PodConditionBreakdownKey(p.podConditionType, p.podConditionStatus, p.podConditionReason)
}

func (p *PodConditionBreakdown) AddOrIncrementContainerState(
containerName string,
podExampleName string,
containerConditionType string,
containerConditionReason string,
containerExampleMessage string,
) *PodConditionBreakdown {
p.containerStateBreakdownBuilders.
Get(containerName).
AddOrIncrementState(podExampleName, containerConditionType, containerConditionReason, containerExampleMessage)
return p
}

func (p *PodConditionBreakdown) IncrementCount() *PodConditionBreakdown {
p.podCount += 1
return p
}

func (p *PodConditionBreakdown) Build() shipper.ClusterCapacityReportBreakdown {

orderedContainers := make([]shipper.ClusterCapacityReportContainerBreakdown, 0)

for _, v := range p.containerStateBreakdownBuilders {
orderedContainers = append(orderedContainers, v.Build())
}

sort.Slice(orderedContainers, func(i, j int) bool {
return orderedContainers[i].Name < orderedContainers[j].Name
})

return shipper.ClusterCapacityReportBreakdown{
Type: p.podConditionType,
Status: p.podConditionStatus,
Count: p.podCount,
Reason: p.podConditionReason,
Containers: orderedContainers,
}
}
Loading