|
| 1 | +// SPDX-License-Identifier: Apache-2.0 |
| 2 | +// Copyright Authors of K9s |
| 3 | + |
| 4 | +package config |
| 5 | + |
| 6 | +import ( |
| 7 | + "fmt" |
| 8 | + "os" |
| 9 | + "path" |
| 10 | + |
| 11 | + "github.com/derailed/k9s/internal/client" |
| 12 | + "gopkg.in/yaml.v2" |
| 13 | +) |
| 14 | + |
| 15 | +var ( |
| 16 | + // Template represents the template of new workload gvr |
| 17 | + Template = []byte(`name: "test.com/v1alpha1/myCRD" |
| 18 | +status: |
| 19 | + cellName: "Status" |
| 20 | + # na: true |
| 21 | +readiness: |
| 22 | + cellName: "Current" |
| 23 | + # The cellExtraName will be shown as cellName/cellExtraName |
| 24 | + cellExtraName: "Desired" |
| 25 | + # na: true |
| 26 | +validity: |
| 27 | + replicas: |
| 28 | + cellCurrentName: "Current" |
| 29 | + cellDesiredName: "Desired" |
| 30 | + # cellAllName: "Ready" |
| 31 | + matchs: |
| 32 | + - cellName: "State" |
| 33 | + cellValue: "Ready"`) |
| 34 | +) |
| 35 | + |
| 36 | +var ( |
| 37 | + // defaultGvr represent the default values uses if a custom gvr is set without status, validity or readiness |
| 38 | + defaultGvr = WorkloadGVR{ |
| 39 | + Status: &GVRStatus{CellName: "Status"}, |
| 40 | + Validity: &GVRValidity{Matchs: []Match{{CellName: "Ready", Value: "True"}}}, |
| 41 | + Readiness: &GVRReadiness{CellName: "Ready"}, |
| 42 | + } |
| 43 | + |
| 44 | + // defaultConfigGVRs represents the default configurations |
| 45 | + defaultConfigGVRs = map[string]WorkloadGVR{ |
| 46 | + "apps/v1/deployments": { |
| 47 | + Name: "apps/v1/deployments", |
| 48 | + Readiness: &GVRReadiness{CellName: "Ready"}, |
| 49 | + Validity: &GVRValidity{ |
| 50 | + Replicas: Replicas{CellAllName: "Ready"}, |
| 51 | + }, |
| 52 | + }, |
| 53 | + "apps/v1/daemonsets": { |
| 54 | + Name: "apps/v1/daemonsets", |
| 55 | + Readiness: &GVRReadiness{CellName: "Ready", CellExtraName: "Desired"}, |
| 56 | + Validity: &GVRValidity{ |
| 57 | + Replicas: Replicas{CellDesiredName: "Desired", CellCurrentName: "Ready"}, |
| 58 | + }, |
| 59 | + }, |
| 60 | + "apps/v1/replicasets": { |
| 61 | + Name: "apps/v1/replicasets", |
| 62 | + Readiness: &GVRReadiness{CellName: "Current", CellExtraName: "Desired"}, |
| 63 | + Validity: &GVRValidity{ |
| 64 | + Replicas: Replicas{CellDesiredName: "Desired", CellCurrentName: "Current"}, |
| 65 | + }, |
| 66 | + }, |
| 67 | + "apps/v1/statefulSets": { |
| 68 | + Name: "apps/v1/statefulSets", |
| 69 | + Status: &GVRStatus{CellName: "Ready"}, |
| 70 | + Readiness: &GVRReadiness{CellName: "Ready"}, |
| 71 | + Validity: &GVRValidity{ |
| 72 | + Replicas: Replicas{CellAllName: "Ready"}, |
| 73 | + }, |
| 74 | + }, |
| 75 | + "v1/pods": { |
| 76 | + Name: "v1/pods", |
| 77 | + Status: &GVRStatus{CellName: "Status"}, |
| 78 | + Readiness: &GVRReadiness{CellName: "Ready"}, |
| 79 | + Validity: &GVRValidity{ |
| 80 | + Matchs: []Match{ |
| 81 | + {CellName: "Status", Value: "Running"}, |
| 82 | + }, |
| 83 | + Replicas: Replicas{CellAllName: "Ready"}, |
| 84 | + }, |
| 85 | + }, |
| 86 | + } |
| 87 | +) |
| 88 | + |
| 89 | +type CellName string |
| 90 | + |
| 91 | +type GVRStatus struct { |
| 92 | + NA bool `json:"na" yaml:"na"` |
| 93 | + CellName CellName `json:"cellName" yaml:"cellName"` |
| 94 | +} |
| 95 | + |
| 96 | +type GVRReadiness struct { |
| 97 | + NA bool `json:"na" yaml:"na"` |
| 98 | + CellName CellName `json:"cellName" yaml:"cellName"` |
| 99 | + CellExtraName CellName `json:"cellExtraName" yaml:"cellExtraName"` |
| 100 | +} |
| 101 | + |
| 102 | +type Match struct { |
| 103 | + CellName CellName `json:"cellName" yaml:"cellName"` |
| 104 | + Value string `json:"cellValue" yaml:"cellValue"` |
| 105 | +} |
| 106 | + |
| 107 | +type Replicas struct { |
| 108 | + CellCurrentName CellName `json:"cellCurrentName" yaml:"cellCurrentName"` |
| 109 | + CellDesiredName CellName `json:"cellDesiredName" yaml:"cellDesiredName"` |
| 110 | + CellAllName CellName `json:"cellAllName" yaml:"cellAllName"` |
| 111 | +} |
| 112 | + |
| 113 | +type GVRValidity struct { |
| 114 | + NA bool `json:"na" yaml:"na"` |
| 115 | + Matchs []Match `json:"matchs,omitempty" yaml:"matchs,omitempty"` |
| 116 | + Replicas Replicas `json:"replicas" yaml:"replicas"` |
| 117 | +} |
| 118 | + |
| 119 | +type WorkloadGVR struct { |
| 120 | + Name string `json:"name" yaml:"name"` |
| 121 | + Status *GVRStatus `json:"status,omitempty" yaml:"status,omitempty"` |
| 122 | + Readiness *GVRReadiness `json:"readiness,omitempty" yaml:"readiness,omitempty"` |
| 123 | + Validity *GVRValidity `json:"validity,omitempty" yaml:"validity,omitempty"` |
| 124 | +} |
| 125 | + |
| 126 | +// TODO: Find better name (maybe moving it to a new file as well) |
| 127 | +type WkC struct { |
| 128 | + GVRFilenames []string `yaml:"wkg"` |
| 129 | +} |
| 130 | + |
| 131 | +// TODO: Explains the parameters |
| 132 | +// NewWorkloadGVRs returns the default GVRs to use if no custom config is set |
| 133 | +func NewWorkloadGVRs(workloadPath string, filenames []string) []WorkloadGVR { |
| 134 | + workloadGVRs := make([]WorkloadGVR, 0) |
| 135 | + for _, gvr := range defaultConfigGVRs { |
| 136 | + workloadGVRs = append(workloadGVRs, gvr) |
| 137 | + } |
| 138 | + |
| 139 | + // Append custom GVRS |
| 140 | + if len(filenames) != 0 { |
| 141 | + for _, filename := range filenames { |
| 142 | + wkgvr, err := GetWorkloadGVRFromFile(path.Join(workloadPath, fmt.Sprintf("%s.%s", filename, "yaml"))) |
| 143 | + if err == nil { |
| 144 | + workloadGVRs = append(workloadGVRs, wkgvr) |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + return workloadGVRs |
| 150 | +} |
| 151 | + |
| 152 | +// GetWorkloadGVRFromFile returns a gvr from a filepath |
| 153 | +func GetWorkloadGVRFromFile(filepath string) (WorkloadGVR, error) { |
| 154 | + yamlFile, err := os.ReadFile(filepath) |
| 155 | + if err != nil { |
| 156 | + return WorkloadGVR{}, err |
| 157 | + } |
| 158 | + |
| 159 | + var wkgvr WorkloadGVR |
| 160 | + if err = yaml.Unmarshal(yamlFile, &wkgvr); err != nil { |
| 161 | + return WorkloadGVR{}, err |
| 162 | + } |
| 163 | + |
| 164 | + return wkgvr, nil |
| 165 | +} |
| 166 | + |
| 167 | +// GetGVR will return the GVR defined by the WorkloadGVR's name |
| 168 | +func (wgvr WorkloadGVR) GetGVR() client.GVR { |
| 169 | + return client.NewGVR(wgvr.Name) |
| 170 | +} |
| 171 | + |
| 172 | +// ApplyDefault will complete the GVR with missing values |
| 173 | +// If it's an existing GVR's name, it will apply their corresponding default values |
| 174 | +// If it's an unknown resources without readiness, status or validity it will use the default ones |
| 175 | +func (wkgvr *WorkloadGVR) ApplyDefault() { |
| 176 | + // Apply default values |
| 177 | + existingGvr, ok := defaultConfigGVRs[wkgvr.Name] |
| 178 | + if ok { |
| 179 | + wkgvr.applyDefaultValues(existingGvr) |
| 180 | + } else { |
| 181 | + wkgvr.applyDefaultValues(defaultGvr) |
| 182 | + } |
| 183 | +} |
| 184 | + |
| 185 | +func (wkgvr *WorkloadGVR) applyDefaultValues(defaultGVR WorkloadGVR) { |
| 186 | + if wkgvr.Status == nil { |
| 187 | + wkgvr.Status = defaultGVR.Status |
| 188 | + } |
| 189 | + |
| 190 | + if wkgvr.Readiness == nil { |
| 191 | + wkgvr.Readiness = defaultGVR.Readiness |
| 192 | + } |
| 193 | + |
| 194 | + if wkgvr.Validity == nil { |
| 195 | + wkgvr.Validity = defaultGVR.Validity |
| 196 | + } |
| 197 | +} |
0 commit comments