Skip to content

Commit

Permalink
basic data structure in place
Browse files Browse the repository at this point in the history
  • Loading branch information
jackfrancis committed Jul 19, 2016
1 parent e010f7a commit bb4d580
Show file tree
Hide file tree
Showing 26 changed files with 1,142 additions and 171 deletions.
63 changes: 61 additions & 2 deletions api/swagger-spec/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,72 @@ definitions:
type: array
items:
$ref: "#/definitions/componentVersion"
k8sResource:
type: object
required:
- data
properties:
data:
type: object
namespace:
type: object
required:
- name
- daemonSets
- deployments
- events
- pods
- replicaSets
- replicationControllers
- services
properties:
name:
type: string
daemonSets:
type: array
items:
$ref: "#/definitions/k8sResource"
deployments:
type: array
items:
$ref: "#/definitions/k8sResource"
events:
type: array
items:
$ref: "#/definitions/k8sResource"
pods:
type: array
items:
$ref: "#/definitions/k8sResource"
replicaSets:
type: array
items:
$ref: "#/definitions/k8sResource"
replicationControllers:
type: array
items:
$ref: "#/definitions/k8sResource"
services:
type: array
items:
$ref: "#/definitions/k8sResource"
doctorInfo:
type: object
required:
- cluster
- workflow
- nodes
- namespaces
properties:
cluster:
workflow:
$ref: "#/definitions/cluster"
nodes:
type: array
items:
$ref: "#/definitions/k8sResource"
namespaces:
type: array
items:
$ref: "#/definitions/namespace"
componentVersion:
type: object
properties:
Expand Down
11 changes: 10 additions & 1 deletion boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ func main() {
}
secretInterface := kubeClient.Secrets(config.Spec.DeisNamespace)
rcInterface := kubeClient.ReplicationControllers(config.Spec.DeisNamespace)
nodeInterface := kubeClient.Nodes()
podInterface := kubeClient.Pods(config.Spec.DeisNamespace)
replicaSetInterface := kubeClient.ExtensionsClient.ReplicaSets(config.Spec.DeisNamespace)
daemonSetInterface := kubeClient.ExtensionsClient.DaemonSets(config.Spec.DeisNamespace)
deploymentInterface := kubeClient.ExtensionsClient.Deployments(config.Spec.DeisNamespace)
serviceInterface := kubeClient.Services(config.Spec.DeisNamespace)
eventInterface := kubeClient.Events(config.Spec.DeisNamespace)
clusterID := data.NewClusterIDFromPersistentStorage(secretInterface)
installedDeisData := data.NewInstalledDeisData(rcInterface)
availableVersion := data.NewAvailableVersionsFromAPI(
Expand Down Expand Up @@ -62,7 +69,9 @@ func main() {
defer close(ch)

// Get a new router, with handler functions
r := handlers.RegisterRoutes(mux.NewRouter(), secretInterface, rcInterface, availableVersion)
r := handlers.RegisterRoutes(mux.NewRouter(), availableVersion, daemonSetInterface,
deploymentInterface, eventInterface, nodeInterface, podInterface, rcInterface,
replicaSetInterface, secretInterface, serviceInterface)
// Bind to a port and pass our router in
hostStr := fmt.Sprintf(":%s", config.Spec.Port)
log.Printf("Serving on %s", hostStr)
Expand Down
6 changes: 4 additions & 2 deletions boot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/deis/workflow-manager/config"
"github.com/deis/workflow-manager/data"
"github.com/deis/workflow-manager/handlers"
"github.com/deis/workflow-manager/k8s"
"github.com/deis/workflow-manager/mocks"
apiclient "github.com/deis/workflow-manager/pkg/swagger/client"
"github.com/gorilla/mux"
Expand All @@ -23,16 +24,17 @@ func newServer(apiClient *apiclient.WorkflowManager) *httptest.Server {
mocks.InstalledMockData{},
&mocks.ClusterIDMockData{},
mocks.LatestMockData{},
data.NewFakeKubeSecretGetterCreator(nil, nil),
k8s.NewFakeKubeSecretGetterCreator(nil, nil),
)
r.Handle("/components", compHdl)
idHdl := handlers.IDHandler(&mocks.ClusterIDMockData{})
r.Handle("/id", idHdl)
docHdl := handlers.DoctorHandler(
mocks.InstalledMockData{},
mocks.RunningK8sMockData{}, // TODO: mock k8s node data
&mocks.ClusterIDMockData{},
mocks.LatestMockData{},
data.NewFakeKubeSecretGetterCreator(nil, nil),
k8s.NewFakeKubeSecretGetterCreator(nil, nil),
apiClient,
)
r.Handle("/doctor", docHdl).Methods("POST")
Expand Down
7 changes: 4 additions & 3 deletions data/available_component_versions.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package data

import (
"github.com/arschles/kubeapp/api/rc"
"github.com/deis/kubeapp/api/rc"
"github.com/deis/workflow-manager/k8s"
"github.com/deis/workflow-manager/pkg/swagger/models"
)

Expand All @@ -13,14 +14,14 @@ type AvailableComponentVersion interface {

// latestReleasedComponent fulfills the AvailableComponentVersion interface
type latestReleasedComponent struct {
secretGetterCreator KubeSecretGetterCreator
secretGetterCreator k8s.KubeSecretGetterCreator
rcLister rc.Lister
availableVersions AvailableVersions
}

// NewLatestReleasedComponent creates a new AvailableComponentVersion that gets the latest released component using sgc as the implementation to get and create secrets
func NewLatestReleasedComponent(
sgc KubeSecretGetterCreator,
sgc k8s.KubeSecretGetterCreator,
rcl rc.Lister,
availableVersions AvailableVersions,
) AvailableComponentVersion {
Expand Down
5 changes: 3 additions & 2 deletions data/available_versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package data
import (
"sync"

"github.com/arschles/kubeapp/api/rc"
"github.com/deis/kubeapp/api/rc"
"github.com/deis/workflow-manager/config"
"github.com/deis/workflow-manager/k8s"
apiclient "github.com/deis/workflow-manager/pkg/swagger/client"
"github.com/deis/workflow-manager/pkg/swagger/client/operations"
"github.com/deis/workflow-manager/pkg/swagger/models"
Expand All @@ -31,7 +32,7 @@ type availableVersionsFromAPI struct {
func NewAvailableVersionsFromAPI(
apiClient *apiclient.WorkflowManager,
baseVersionsURL string,
secretGetterCreator KubeSecretGetterCreator,
secretGetterCreator k8s.KubeSecretGetterCreator,
rcLister rc.Lister,
) AvailableVersions {
if baseVersionsURL == "" {
Expand Down
64 changes: 64 additions & 0 deletions data/available_versions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package data

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"sync"
Expand All @@ -13,6 +14,69 @@ import (
"github.com/deis/workflow-manager/pkg/swagger/models"
)

// Creating a novel mock struct that fulfills the AvailableVersions interface
type testAvailableVersions struct{}

func (a testAvailableVersions) Refresh(cluster models.Cluster) ([]models.ComponentVersion, error) {
data := getMockComponentVersions()
var componentVersions []models.ComponentVersion
_ = json.Unmarshal(data, &componentVersions)
return componentVersions, nil
}

func (a testAvailableVersions) Store(c []models.ComponentVersion) {
return
}

func (a testAvailableVersions) Cached() []models.ComponentVersion {
return nil
}

// Creating another mock struct that fulfills the AvailableVersions interface
type shouldBypassAvailableVersions struct{}

func (a shouldBypassAvailableVersions) Refresh(cluster models.Cluster) ([]models.ComponentVersion, error) {
var componentVersions []models.ComponentVersion
data := []byte(fmt.Sprintf(`[{
"components": [
{
"component": {
"name": "bypass me",
"description": "bypass me"
},
"version": {
"version": "v2-bypass"
}
}
]
}]`))
_ = json.Unmarshal(data, &componentVersions)
return componentVersions, nil
}

func (a shouldBypassAvailableVersions) Store(c []models.ComponentVersion) {
return
}

func (a shouldBypassAvailableVersions) Cached() []models.ComponentVersion {
return nil
}

// Calls GetAvailableVersions twice, the first time we expect our passed-in struct w/ Refresh() method
// to be invoked, the 2nd time we expect to receive the same value back (cached in memory)
// and for the passed-in Refresh() method to be ignored
func TestGetAvailableVersions(t *testing.T) {
mock := getMockComponentVersions()
var mockVersions []models.ComponentVersion
assert.NoErr(t, json.Unmarshal(mock, &mockVersions))
versions, err := GetAvailableVersions(testAvailableVersions{}, models.Cluster{})
assert.NoErr(t, err)
assert.Equal(t, versions, mockVersions, "component versions data")
versions, err = GetAvailableVersions(shouldBypassAvailableVersions{}, models.Cluster{})
assert.NoErr(t, err)
assert.Equal(t, versions, mockVersions, "component versions data")
}

func TestRefreshAvailableVersions(t *testing.T) {
desc := "this is test1"
updAvail := "nothing"
Expand Down
5 changes: 3 additions & 2 deletions data/cluster_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package data
import (
"sync"

"github.com/deis/workflow-manager/k8s"
"github.com/satori/go.uuid"
"k8s.io/kubernetes/pkg/api"
apierrors "k8s.io/kubernetes/pkg/api/errors"
Expand Down Expand Up @@ -36,11 +37,11 @@ func GetID(id ClusterID) (string, error) {
type clusterIDFromPersistentStorage struct {
rwm *sync.RWMutex
cache string
secretGetterCreator KubeSecretGetterCreator
secretGetterCreator k8s.KubeSecretGetterCreator
}

// NewClusterIDFromPersistentStorage returns a new ClusterID implementation that uses the kubernetes API to get its cluster information
func NewClusterIDFromPersistentStorage(sgc KubeSecretGetterCreator) ClusterID {
func NewClusterIDFromPersistentStorage(sgc k8s.KubeSecretGetterCreator) ClusterID {
return &clusterIDFromPersistentStorage{
rwm: new(sync.RWMutex),
cache: "",
Expand Down
55 changes: 33 additions & 22 deletions data/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package data
import (
"encoding/json"
"fmt"
"log"
"strings"

"github.com/arschles/kubeapp/api/rc"
"github.com/deis/kubeapp/api/rc"
"github.com/deis/workflow-manager/config"
"github.com/deis/workflow-manager/k8s"
"github.com/deis/workflow-manager/pkg/swagger/models"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/labels"
)

const (
Expand All @@ -21,7 +22,7 @@ func GetCluster(
c InstalledData,
i ClusterID,
v AvailableComponentVersion,
secretGetterCreator KubeSecretGetterCreator,
secretGetterCreator k8s.KubeSecretGetterCreator,
) (models.Cluster, error) {

// Populate cluster object with installed components
Expand All @@ -31,7 +32,7 @@ func GetCluster(
}
err = AddUpdateData(&cluster, v, secretGetterCreator)
if err != nil {
return models.Cluster{}, err
log.Println("unable to decorate cluster data with available updates data")
}
// Get the cluster ID
id, err := GetID(i)
Expand All @@ -45,7 +46,7 @@ func GetCluster(

// AddUpdateData adds UpdateAvailable field data to cluster components
// Any cluster object modifications are made "in-place"
func AddUpdateData(c *models.Cluster, v AvailableComponentVersion, secretGetterCreator KubeSecretGetterCreator) error {
func AddUpdateData(c *models.Cluster, v AvailableComponentVersion, secretGetterCreator k8s.KubeSecretGetterCreator) error {
// Determine if any components have an available update
for i, component := range c.Components {
installed := component.Version.Version
Expand Down Expand Up @@ -93,7 +94,7 @@ func GetInstalled(g InstalledData) (models.Cluster, error) {
// GetLatestVersion returns the latest known version of a deis component
func GetLatestVersion(
component string,
secretGetterCreator KubeSecretGetterCreator,
secretGetterCreator k8s.KubeSecretGetterCreator,
rcLister rc.Lister,
cluster models.Cluster,
availVsns AvailableVersions,
Expand Down Expand Up @@ -139,31 +140,41 @@ func NewestSemVer(v1 string, v2 string) (string, error) {
return v1, nil
}

// getRCItems is a helper function that returns a slice of
// ReplicationController objects given a rc.Lister interface
func getRCItems(rcLister rc.Lister) ([]api.ReplicationController, error) {
rcs, err := rcLister.List(api.ListOptions{
LabelSelector: labels.Everything(),
})
if err != nil {
return []api.ReplicationController{}, err
}
return rcs.Items, nil
}

// GetDoctorInfo collects doctor info and return DoctorInfo struct
func GetDoctorInfo(
c InstalledData,
c InstalledData, // workflow cluster data
k k8s.RunningK8sData, // k8s data
i ClusterID,
v AvailableComponentVersion,
secretGetterCreator KubeSecretGetterCreator,
secretGetterCreator k8s.KubeSecretGetterCreator,
) (models.DoctorInfo, error) {
cluster, err := GetCluster(c, i, v, secretGetterCreator)
if err != nil {
return models.DoctorInfo{}, err
}
nodes, _ := k8s.GetNodesModels(k)
pods, _ := k8s.GetPodsModels(k)
services, _ := k8s.GetServicesModels(k)
replicationControllers, _ := k8s.GetReplicationControllersModels(k)
replicaSets, _ := k8s.GetReplicaSetsModels(k)
daemonSets, _ := k8s.GetDaemonSetsModels(k)
deployments, _ := k8s.GetDeploymentsModels(k)
events, _ := k8s.GetEventsModels(k)
var namespaces []*models.Namespace
namespaces = append(namespaces, &models.Namespace{
Name: config.Spec.DeisNamespace,
DaemonSets: daemonSets,
Deployments: deployments,
Events: events,
Pods: pods,
ReplicaSets: replicaSets,
ReplicationControllers: replicationControllers,
Services: services,
})
doctor := models.DoctorInfo{
Cluster: &cluster,
Workflow: &cluster,
Nodes: nodes,
Namespaces: namespaces,
}
return doctor, nil
}
Expand Down
Loading

0 comments on commit bb4d580

Please sign in to comment.