Skip to content
This repository was archived by the owner on Aug 5, 2020. It is now read-only.

Commit 84206b2

Browse files
authored
deis doctor includes lots of k8s data (#81)
* basic data structure in place * fix(misc): err responses, code cleanup, light optimizations * chore(cleanup): err response, enumeration, log optimizations * chore(err): `if err :=` is preferred over `if err =`
1 parent e010f7a commit 84206b2

24 files changed

Lines changed: 1191 additions & 212 deletions

api/swagger-spec/swagger.yml

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,72 @@ definitions:
311311
type: array
312312
items:
313313
$ref: "#/definitions/componentVersion"
314+
k8sResource:
315+
type: object
316+
required:
317+
- data
318+
properties:
319+
data:
320+
type: object
321+
namespace:
322+
type: object
323+
required:
324+
- name
325+
- daemonSets
326+
- deployments
327+
- events
328+
- pods
329+
- replicaSets
330+
- replicationControllers
331+
- services
332+
properties:
333+
name:
334+
type: string
335+
daemonSets:
336+
type: array
337+
items:
338+
$ref: "#/definitions/k8sResource"
339+
deployments:
340+
type: array
341+
items:
342+
$ref: "#/definitions/k8sResource"
343+
events:
344+
type: array
345+
items:
346+
$ref: "#/definitions/k8sResource"
347+
pods:
348+
type: array
349+
items:
350+
$ref: "#/definitions/k8sResource"
351+
replicaSets:
352+
type: array
353+
items:
354+
$ref: "#/definitions/k8sResource"
355+
replicationControllers:
356+
type: array
357+
items:
358+
$ref: "#/definitions/k8sResource"
359+
services:
360+
type: array
361+
items:
362+
$ref: "#/definitions/k8sResource"
314363
doctorInfo:
315364
type: object
316365
required:
317-
- cluster
366+
- workflow
367+
- nodes
368+
- namespaces
318369
properties:
319-
cluster:
370+
workflow:
320371
$ref: "#/definitions/cluster"
372+
nodes:
373+
type: array
374+
items:
375+
$ref: "#/definitions/k8sResource"
376+
namespaces:
377+
type: array
378+
items:
379+
$ref: "#/definitions/namespace"
321380
componentVersion:
322381
type: object
323382
properties:

boot.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/deis/workflow-manager/data"
1111
"github.com/deis/workflow-manager/handlers"
1212
"github.com/deis/workflow-manager/jobs"
13+
"github.com/deis/workflow-manager/k8s"
1314
"github.com/gorilla/mux"
1415
kcl "k8s.io/kubernetes/pkg/client/unversioned"
1516
)
@@ -23,25 +24,20 @@ func main() {
2324
if err != nil {
2425
log.Fatalf("Error creating new swagger api client (%s)", err)
2526
}
26-
secretInterface := kubeClient.Secrets(config.Spec.DeisNamespace)
27-
rcInterface := kubeClient.ReplicationControllers(config.Spec.DeisNamespace)
28-
clusterID := data.NewClusterIDFromPersistentStorage(secretInterface)
29-
installedDeisData := data.NewInstalledDeisData(rcInterface)
27+
deisK8sResources := k8s.NewResourceInterfaceNamespaced(kubeClient, config.Spec.DeisNamespace)
28+
clusterID := data.NewClusterIDFromPersistentStorage(deisK8sResources.Secrets())
29+
installedDeisData := data.NewInstalledDeisData(deisK8sResources)
3030
availableVersion := data.NewAvailableVersionsFromAPI(
3131
apiClient,
3232
config.Spec.VersionsAPIURL,
33-
secretInterface,
34-
rcInterface,
3533
)
36-
availableComponentVersion := data.NewLatestReleasedComponent(secretInterface, rcInterface, availableVersion)
34+
availableComponentVersion := data.NewLatestReleasedComponent(deisK8sResources, availableVersion)
3735

3836
pollDur := time.Duration(config.Spec.Polling) * time.Second
3937
// we want to do the following jobs according to our remote API interval:
4038
// 1. get latest stable deis component versions
4139
// 2. send diagnostic data, if appropriate
4240
glvdPeriodic := jobs.NewGetLatestVersionDataPeriodic(
43-
secretInterface,
44-
rcInterface,
4541
installedDeisData,
4642
clusterID,
4743
availableVersion,
@@ -51,8 +47,7 @@ func main() {
5147

5248
svPeriodic := jobs.NewSendVersionsPeriodic(
5349
apiClient,
54-
secretInterface,
55-
rcInterface,
50+
deisK8sResources,
5651
availableVersion,
5752
pollDur,
5853
)
@@ -62,7 +57,7 @@ func main() {
6257
defer close(ch)
6358

6459
// Get a new router, with handler functions
65-
r := handlers.RegisterRoutes(mux.NewRouter(), secretInterface, rcInterface, availableVersion)
60+
r := handlers.RegisterRoutes(mux.NewRouter(), availableVersion, deisK8sResources)
6661
// Bind to a port and pass our router in
6762
hostStr := fmt.Sprintf(":%s", config.Spec.Port)
6863
log.Printf("Serving on %s", hostStr)

boot_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ func newServer(apiClient *apiclient.WorkflowManager) *httptest.Server {
2323
mocks.InstalledMockData{},
2424
&mocks.ClusterIDMockData{},
2525
mocks.LatestMockData{},
26-
data.NewFakeKubeSecretGetterCreator(nil, nil),
2726
)
2827
r.Handle("/components", compHdl)
2928
idHdl := handlers.IDHandler(&mocks.ClusterIDMockData{})
3029
r.Handle("/id", idHdl)
3130
docHdl := handlers.DoctorHandler(
3231
mocks.InstalledMockData{},
32+
mocks.RunningK8sMockData{}, // TODO: mock k8s node data
3333
&mocks.ClusterIDMockData{},
3434
mocks.LatestMockData{},
35-
data.NewFakeKubeSecretGetterCreator(nil, nil),
3635
apiClient,
3736
)
3837
r.Handle("/doctor", docHdl).Methods("POST")

data/available_component_versions.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package data
22

33
import (
4-
"github.com/arschles/kubeapp/api/rc"
4+
"github.com/deis/workflow-manager/k8s"
55
"github.com/deis/workflow-manager/pkg/swagger/models"
66
)
77

@@ -13,30 +13,25 @@ type AvailableComponentVersion interface {
1313

1414
// latestReleasedComponent fulfills the AvailableComponentVersion interface
1515
type latestReleasedComponent struct {
16-
secretGetterCreator KubeSecretGetterCreator
17-
rcLister rc.Lister
18-
availableVersions AvailableVersions
16+
k8sResources *k8s.ResourceInterfaceNamespaced
17+
availableVersions AvailableVersions
1918
}
2019

2120
// NewLatestReleasedComponent creates a new AvailableComponentVersion that gets the latest released component using sgc as the implementation to get and create secrets
2221
func NewLatestReleasedComponent(
23-
sgc KubeSecretGetterCreator,
24-
rcl rc.Lister,
22+
ri *k8s.ResourceInterfaceNamespaced,
2523
availableVersions AvailableVersions,
2624
) AvailableComponentVersion {
2725
return &latestReleasedComponent{
28-
secretGetterCreator: sgc,
29-
rcLister: rcl,
30-
availableVersions: availableVersions,
26+
k8sResources: ri,
27+
availableVersions: availableVersions,
3128
}
3229
}
3330

3431
// Get method for LatestReleasedComponent
3532
func (c *latestReleasedComponent) Get(component string, cluster models.Cluster) (models.Version, error) {
3633
version, err := GetLatestVersion(
3734
component,
38-
c.secretGetterCreator,
39-
c.rcLister,
4035
cluster,
4136
c.availableVersions,
4237
)

data/available_versions.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package data
33
import (
44
"sync"
55

6-
"github.com/arschles/kubeapp/api/rc"
76
"github.com/deis/workflow-manager/config"
87
apiclient "github.com/deis/workflow-manager/pkg/swagger/client"
98
"github.com/deis/workflow-manager/pkg/swagger/client/operations"
@@ -31,8 +30,6 @@ type availableVersionsFromAPI struct {
3130
func NewAvailableVersionsFromAPI(
3231
apiClient *apiclient.WorkflowManager,
3332
baseVersionsURL string,
34-
secretGetterCreator KubeSecretGetterCreator,
35-
rcLister rc.Lister,
3633
) AvailableVersions {
3734
if baseVersionsURL == "" {
3835
baseVersionsURL = config.Spec.VersionsAPIURL

data/available_versions_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package data
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"net/http"
67
"net/http/httptest"
78
"sync"
@@ -13,6 +14,73 @@ import (
1314
"github.com/deis/workflow-manager/pkg/swagger/models"
1415
)
1516

17+
// Creating a novel mock struct that fulfills the AvailableVersions interface
18+
type testAvailableVersions struct{}
19+
20+
func (a testAvailableVersions) Refresh(cluster models.Cluster) ([]models.ComponentVersion, error) {
21+
data := getMockComponentVersions()
22+
var componentVersions []models.ComponentVersion
23+
if err := json.Unmarshal(data, &componentVersions); err != nil {
24+
return nil, err
25+
}
26+
return componentVersions, nil
27+
}
28+
29+
func (a testAvailableVersions) Store(c []models.ComponentVersion) {
30+
return
31+
}
32+
33+
func (a testAvailableVersions) Cached() []models.ComponentVersion {
34+
return nil
35+
}
36+
37+
// Creating another mock struct that fulfills the AvailableVersions interface
38+
type shouldBypassAvailableVersions struct{}
39+
40+
func (a shouldBypassAvailableVersions) Refresh(cluster models.Cluster) ([]models.ComponentVersion, error) {
41+
var componentVersions []models.ComponentVersion
42+
data := []byte(fmt.Sprintf(`[{
43+
"components": [
44+
{
45+
"component": {
46+
"name": "bypass me",
47+
"description": "bypass me"
48+
},
49+
"version": {
50+
"version": "v2-bypass"
51+
}
52+
}
53+
]
54+
}]`))
55+
if err := json.Unmarshal(data, &componentVersions); err != nil {
56+
return nil, err
57+
}
58+
return componentVersions, nil
59+
}
60+
61+
func (a shouldBypassAvailableVersions) Store(c []models.ComponentVersion) {
62+
return
63+
}
64+
65+
func (a shouldBypassAvailableVersions) Cached() []models.ComponentVersion {
66+
return nil
67+
}
68+
69+
// Calls GetAvailableVersions twice, the first time we expect our passed-in struct w/ Refresh() method
70+
// to be invoked, the 2nd time we expect to receive the same value back (cached in memory)
71+
// and for the passed-in Refresh() method to be ignored
72+
func TestGetAvailableVersions(t *testing.T) {
73+
mock := getMockComponentVersions()
74+
var mockVersions []models.ComponentVersion
75+
assert.NoErr(t, json.Unmarshal(mock, &mockVersions))
76+
versions, err := GetAvailableVersions(testAvailableVersions{}, models.Cluster{})
77+
assert.NoErr(t, err)
78+
assert.Equal(t, versions, mockVersions, "component versions data")
79+
versions, err = GetAvailableVersions(shouldBypassAvailableVersions{}, models.Cluster{})
80+
assert.NoErr(t, err)
81+
assert.Equal(t, versions, mockVersions, "component versions data")
82+
}
83+
1684
func TestRefreshAvailableVersions(t *testing.T) {
1785
desc := "this is test1"
1886
updAvail := "nothing"

data/cluster_id.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package data
33
import (
44
"sync"
55

6+
"github.com/deis/workflow-manager/k8s"
67
"github.com/satori/go.uuid"
78
"k8s.io/kubernetes/pkg/api"
89
apierrors "k8s.io/kubernetes/pkg/api/errors"
@@ -36,11 +37,11 @@ func GetID(id ClusterID) (string, error) {
3637
type clusterIDFromPersistentStorage struct {
3738
rwm *sync.RWMutex
3839
cache string
39-
secretGetterCreator KubeSecretGetterCreator
40+
secretGetterCreator k8s.KubeSecretGetterCreator
4041
}
4142

4243
// NewClusterIDFromPersistentStorage returns a new ClusterID implementation that uses the kubernetes API to get its cluster information
43-
func NewClusterIDFromPersistentStorage(sgc KubeSecretGetterCreator) ClusterID {
44+
func NewClusterIDFromPersistentStorage(sgc k8s.KubeSecretGetterCreator) ClusterID {
4445
return &clusterIDFromPersistentStorage{
4546
rwm: new(sync.RWMutex),
4647
cache: "",

0 commit comments

Comments
 (0)