Refactor cluster status command
This patch moves all cluster status functionality from cmd level to pkg level as well as unit tests, making code cleaner and improving actual test coverage. Change-Id: Ia811887b684b2129ca30dd90b5afc72e726271ff Signed-off-by: Ruslan Aliev <raliev@mirantis.com>changes/44/746844/15
parent
29088b7b42
commit
94d99c85d0
@ -1 +0,0 @@
|
||||
Kind Name Status
|
@ -1,3 +0,0 @@
|
||||
Kind Name Status
|
||||
Resource pending-resource Pending
|
||||
Resource stable-resource Stable
|
@ -1,40 +0,0 @@
|
||||
# this CRD defines a type whose status can be checked using the condition in
|
||||
# the annotations
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: resources.example.com
|
||||
annotations:
|
||||
airshipit.org/status-check: |
|
||||
[
|
||||
{
|
||||
"status": "Stable",
|
||||
"condition": "@.status.state==\"stable\""
|
||||
},
|
||||
{
|
||||
"status": "Pending",
|
||||
"condition": "@.status.state==\"pending\""
|
||||
}
|
||||
]
|
||||
spec:
|
||||
group: example.com
|
||||
versions:
|
||||
- name: v1
|
||||
served: true
|
||||
storage: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
state:
|
||||
type: string
|
||||
scope: Namespaced
|
||||
names:
|
||||
plural: resources
|
||||
singular: resource
|
||||
kind: Resource
|
||||
shortNames:
|
||||
- rsc
|
@ -1,8 +0,0 @@
|
||||
resources:
|
||||
- crd.yaml
|
||||
- stable-resource.yaml
|
||||
- pending-resource.yaml
|
||||
- missing.yaml
|
||||
- unknown.yaml
|
||||
- legacy-crd.yaml
|
||||
- legacy-resource.yaml
|
@ -1,42 +0,0 @@
|
||||
# this is a legacy CRD which defines a type whose status can be checked using
|
||||
# the condition in the annotations
|
||||
# It is included in tests to assure backward compatibility
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: legacies.example.com
|
||||
annotations:
|
||||
airshipit.org/status-check: |
|
||||
[
|
||||
{
|
||||
"status": "Stable",
|
||||
"condition": "@.status.state==\"stable\""
|
||||
},
|
||||
{
|
||||
"status": "Pending",
|
||||
"condition": "@.status.state==\"pending\""
|
||||
}
|
||||
]
|
||||
spec:
|
||||
group: example.com
|
||||
versions:
|
||||
- name: v1
|
||||
served: true
|
||||
storage: true
|
||||
scope: Namespaced
|
||||
names:
|
||||
plural: legacies
|
||||
singular: legacy
|
||||
kind: Legacy
|
||||
shortNames:
|
||||
- lgc
|
||||
preserveUnknownFields: false
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
state:
|
||||
type: string
|
@ -1,7 +0,0 @@
|
||||
# this legacy-resource is stable because the fake version in the cluster will
|
||||
# have .status.state == "stable"
|
||||
apiVersion: "example.com/v1"
|
||||
kind: Legacy
|
||||
metadata:
|
||||
name: stable-legacy
|
||||
namespace: default
|
@ -1,7 +0,0 @@
|
||||
# This resource doesn't have a status-check defined by its CRD (which is also
|
||||
# missing for brevity). Requesting its status is an error
|
||||
apiVersion: "example.com/v1"
|
||||
kind: Missing
|
||||
metadata:
|
||||
name: missing-resource
|
||||
namespace: default
|
@ -1,7 +0,0 @@
|
||||
# this resource is pending because the fake version in the cluster will
|
||||
# have .status.state == "pending"
|
||||
apiVersion: "example.com/v1"
|
||||
kind: Resource
|
||||
metadata:
|
||||
name: pending-resource
|
||||
namespace: default
|
@ -1,7 +0,0 @@
|
||||
# this resource is stable because the fake version in the cluster will have
|
||||
# .status.state == "stable"
|
||||
apiVersion: "example.com/v1"
|
||||
kind: Resource
|
||||
metadata:
|
||||
name: stable-resource
|
||||
namespace: default
|
@ -1,8 +0,0 @@
|
||||
# this resource is in an unknown state because the fake version in the cluster
|
||||
# will have .status.state == "unknown", which does not correlate to any of the
|
||||
# status checks in the CRD.
|
||||
apiVersion: "example.com/v1"
|
||||
kind: Resource
|
||||
metadata:
|
||||
name: unknown
|
||||
namespace: default
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
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
|
||||
|
||||
https://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 cluster
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/log"
|
||||
"opendev.org/airship/airshipctl/pkg/util"
|
||||
)
|
||||
|
||||
// StatusRunner runs internal logic of cluster status command
|
||||
func StatusRunner(o StatusOptions, w io.Writer) error {
|
||||
statusMap, docs, err := o.GetStatusMapDocs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var errors []error
|
||||
tw := util.NewTabWriter(w)
|
||||
fmt.Fprintf(tw, "Kind\tName\tStatus\n")
|
||||
for _, doc := range docs {
|
||||
status, err := statusMap.GetStatusForResource(doc)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
} else {
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\n", doc.GetKind(), doc.GetName(), status)
|
||||
}
|
||||
}
|
||||
tw.Flush()
|
||||
|
||||
if len(errors) > 0 {
|
||||
log.Debug("The following errors occurred while requesting the status:")
|
||||
for _, statusErr := range errors {
|
||||
log.Debug(statusErr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
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
|
||||
|
||||
https://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 cluster_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"opendev.org/airship/airshipctl/pkg/cluster"
|
||||
"opendev.org/airship/airshipctl/pkg/document"
|
||||
"opendev.org/airship/airshipctl/pkg/k8s/client/fake"
|
||||
)
|
||||
|
||||
type mockStatusOptions struct{}
|
||||
|
||||
func (o mockStatusOptions) GetStatusMapDocs() (*cluster.StatusMap, []document.Document, error) {
|
||||
fakeClient := fake.NewClient(
|
||||
fake.WithCRDs(makeResourceCRD(annotationValidStatusCheck())),
|
||||
fake.WithDynamicObjects(makeResource("stable-resource", "stable")))
|
||||
fakeSM, err := cluster.NewStatusMap(fakeClient)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fakeDocBundle, err := document.NewBundleByPath("testdata/statusmap")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fakeDocs, err := fakeDocBundle.GetAllDocuments()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return fakeSM, fakeDocs, nil
|
||||
}
|
||||
|
||||
func TestStatusRunner(t *testing.T) {
|
||||
statusOptions := mockStatusOptions{}
|
||||
b := bytes.NewBuffer(nil)
|
||||
err := cluster.StatusRunner(statusOptions, b)
|
||||
require.NoError(t, err)
|
||||
expectedOutput := fmt.Sprintf("Kind Name Status Resource stable-resource Stable ")
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(b.String(), " ")
|
||||
assert.Equal(t, expectedOutput, str)
|
||||
}
|
Loading…
Reference in New Issue