Skip to content

Commit

Permalink
chore(fabric8-services#678): refactor core functionality to be more …
Browse files Browse the repository at this point in the history
…extensible and replace oc commands (fabric8-services#747)
  • Loading branch information
MatousJobanek authored Feb 6, 2019
1 parent 663fa75 commit 9c2ea27
Show file tree
Hide file tree
Showing 61 changed files with 6,683 additions and 2,483 deletions.
10 changes: 9 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions auth/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"net/http"
)

const InternalFeatureLevel = "internal"

type Service interface {
GetUser(ctx context.Context) (*User, error)
GetAuthURL() string
Expand Down
26 changes: 26 additions & 0 deletions cluster/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/fabric8-services/fabric8-tenant/auth"
authclient "github.com/fabric8-services/fabric8-tenant/auth/client"
"github.com/fabric8-services/fabric8-tenant/configuration"
"github.com/fabric8-services/fabric8-tenant/environment"
"github.com/pkg/errors"
"io/ioutil"
"strings"
Expand All @@ -27,12 +28,17 @@ type Cluster struct {
Token string
}

// GetCluster returns a cluster for the given target if it is one of the clusters assigned to the user stored in the given context, error otherwise
type GetCluster func(ctx context.Context, target string) (Cluster, error)

// ForType returns a cluster assigned for the given environment type
type ForType func(envType environment.Type) Cluster

// Service the interface for the cluster service
type Service interface {
GetCluster(ctx context.Context, target string) (Cluster, error)
GetClusters(ctx context.Context) []Cluster
GetUserClusterForType(ctx context.Context, user *auth.User) (ForType, error)
Start() error
Stop()
}
Expand Down Expand Up @@ -87,6 +93,26 @@ func (s *clusterService) Start() error {
return nil
}

// GetUserClusterForType retrieves all clusters assigned to the user represented by the given context and maps it by environment types,
// the function returned by this method represents this cluster-environment-type mapping
func (s *clusterService) GetUserClusterForType(ctx context.Context, user *auth.User) (ForType, error) {
cluster, err := s.GetCluster(ctx, *user.UserData.Cluster)
if err != nil {
return nil, err
}

return func(envType environment.Type) Cluster {
return cluster
}, nil
}

// ForTypeMapping takes the given map and wraps it by the ForType function that returns values from the map based on the keys
func ForTypeMapping(mapping map[environment.Type]Cluster) ForType {
return func(envType environment.Type) Cluster {
return mapping[envType]
}
}

func (s *clusterService) GetCluster(ctx context.Context, target string) (Cluster, error) {
for _, cluster := range s.GetClusters(ctx) {
if cleanURL(target) == cleanURL(cluster.APIURL) {
Expand Down
26 changes: 26 additions & 0 deletions cluster/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import (
"testing"
"time"

"github.com/fabric8-services/fabric8-common/convert/ptr"
"github.com/fabric8-services/fabric8-tenant/auth"
authclient "github.com/fabric8-services/fabric8-tenant/auth/client"
"github.com/fabric8-services/fabric8-tenant/cluster"
"github.com/fabric8-services/fabric8-tenant/configuration"
"github.com/fabric8-services/fabric8-tenant/environment"
testsupport "github.com/fabric8-services/fabric8-tenant/test"
"github.com/fabric8-services/fabric8-tenant/test/doubles"
"github.com/fabric8-services/fabric8-tenant/test/recorder"
Expand Down Expand Up @@ -145,4 +149,26 @@ func TestGetClusters(t *testing.T) {
}
})
})

t.Run("get cluster for user mapped by type", func(t *testing.T) {
// given
clusterService := cluster.NewClusterService(time.Hour, authService)
err := clusterService.Start()
require.NoError(t, err)
defer clusterService.Stop()
user := &auth.User{UserData: &authclient.UserDataAttributes{
Cluster: ptr.String("http://api.cluster1/"),
}}
// when
clusterForType, err := clusterService.GetUserClusterForType(context.Background(), user)
// then
assert.NoError(t, err)
for _, envType := range environment.DefaultEnvTypes {
assert.Equal(t, "http://api.cluster1/", clusterForType(envType).APIURL)
assert.Equal(t, "foo", clusterForType(envType).AppDNS)
assert.Equal(t, "http://console.cluster1/console/", clusterForType(envType).ConsoleURL)
assert.Equal(t, "http://metrics.cluster1/", clusterForType(envType).MetricsURL)
assert.Equal(t, "http://logging.cluster1/", clusterForType(envType).LoggingURL)
}
})
}
7 changes: 7 additions & 0 deletions configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
varTemplateRecommenderAPIToken = "template.recommender.api.token"
varTemplateDomain = "template.domain"
varTemplateCheMultiTenantServer = "template.che.multitenant.server"
varAPIServerUseTLS = "api.server.use.tls"
varAPIServerInsecureSkipTLSVerify = "api.server.insecure.skip.tls.verify"
varLogLevel = "log.level"
varLogJSON = "log.json"
Expand Down Expand Up @@ -126,6 +127,7 @@ func (c *Data) setConfigDefaults() {
//-----
c.v.SetDefault(varKeycloakOpenshiftBroker, defaultKeycloakOpenshiftBroker)
c.v.SetDefault(varOpenshiftUseCurrentCluster, false)
c.v.SetDefault(varAPIServerUseTLS, true)
c.v.SetDefault(varAPIServerInsecureSkipTLSVerify, false)
c.v.SetDefault(varAuthURL, defaultAuthURL)
c.v.SetDefault(varClustersRefreshDelay, defaultClustersRefreshDelay)
Expand Down Expand Up @@ -318,6 +320,11 @@ func (c *Data) UseOpenshiftCurrentCluster() bool {
return c.v.GetBool(varOpenshiftUseCurrentCluster)
}

// APIServerUseTLS returns if the server uses secured HTTPS connections.
func (c *Data) APIServerUseTLS() bool {
return c.v.GetBool(varAPIServerUseTLS)
}

// APIServerInsecureSkipTLSVerify returns if the server's certificate should be checked for validity. This will make your HTTPS connections insecure.
func (c *Data) APIServerInsecureSkipTLSVerify() bool {
return c.v.GetBool(varAPIServerInsecureSkipTLSVerify)
Expand Down
54 changes: 54 additions & 0 deletions controller/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package controller

import (
"context"
"github.com/fabric8-services/fabric8-common/convert/ptr"
"github.com/fabric8-services/fabric8-tenant/app"
"github.com/fabric8-services/fabric8-tenant/cluster"
"github.com/fabric8-services/fabric8-tenant/sentry"
"github.com/fabric8-services/fabric8-tenant/tenant"
)

type NamespaceFilter func(namespace tenant.Namespace) bool
type ClusterResolver func(ctx context.Context, target string) (cluster.Cluster, error)

func convertTenant(ctx context.Context, tenant *tenant.Tenant, namespaces []*tenant.Namespace, resolveCluster ClusterResolver) *app.Tenant {
nsAttributes := make([]*app.NamespaceAttributes, 0)

for _, ns := range namespaces {

nsCluster, err := resolveCluster(ctx, ns.MasterURL)
if err != nil {
sentry.LogError(ctx, map[string]interface{}{
"err": err,
"cluster_url": ns.MasterURL,
}, err, "unable to resolve nsCluster")
nsCluster = cluster.Cluster{}
}
nsAttributes = append(nsAttributes, &app.NamespaceAttributes{
CreatedAt: &ns.CreatedAt,
UpdatedAt: &ns.UpdatedAt,
ClusterURL: &ns.MasterURL,
ClusterAppDomain: &nsCluster.AppDNS,
ClusterConsoleURL: &nsCluster.ConsoleURL,
ClusterMetricsURL: &nsCluster.MetricsURL,
ClusterLoggingURL: &nsCluster.LoggingURL,
Name: &ns.Name,
Type: ptr.String(ns.Type.String()),
Version: &ns.Version,
State: ptr.String(ns.State.String()),
ClusterCapacityExhausted: &nsCluster.CapacityExhausted,
})
}

return &app.Tenant{
ID: &tenant.ID,
Type: "tenants",
Attributes: &app.TenantAttributes{
CreatedAt: &tenant.CreatedAt,
Email: &tenant.Email,
Profile: &tenant.Profile,
Namespaces: nsAttributes,
},
}
}
114 changes: 114 additions & 0 deletions controller/convert_whitebox_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package controller

import (
"context"
"testing"
"time"

"github.com/fabric8-services/fabric8-tenant/app"
"github.com/fabric8-services/fabric8-tenant/cluster"
"github.com/fabric8-services/fabric8-tenant/tenant"

"github.com/fabric8-services/fabric8-tenant/environment"
"github.com/satori/go.uuid"
"github.com/stretchr/testify/require"
)

var resolveCluster = func(ctx context.Context, target string) (cluster.Cluster, error) {
return cluster.Cluster{
AppDNS: "apps.example.com",
ConsoleURL: "https://console.example.com/console",
MetricsURL: "https://metrics.example.com",
LoggingURL: "https://console.example.com/console", // not a typo; logging and console are on the same host
CapacityExhausted: true,
}, nil
}

func namespaces(ns1, ns2 time.Time) []*tenant.Namespace {
return []*tenant.Namespace{
{
CreatedAt: ns1,
UpdatedAt: ns1,
MasterURL: "http://test1.org",
Name: "test-che",
Type: environment.TypeChe,
Version: "1.0",
State: "created",
},
{
CreatedAt: ns2,
UpdatedAt: ns2,
MasterURL: "http://test2.org",
Name: "test-jenkins",
Type: environment.TypeJenkins,
Version: "1.0",
State: "created",
},
}
}

func TestConvertTenant(t *testing.T) {
ctx := context.Background()

tenantCreated := time.Now()
tenantID := uuid.NewV4()
tenant := &tenant.Tenant{
ID: tenantID,
Email: "[email protected]",
Profile: "Q X",
CreatedAt: tenantCreated,
}

ns1Time, ns2Time := time.Now(), time.Now()
namespaces := namespaces(ns1Time, ns2Time)
want := &app.Tenant{
ID: &tenantID,
Type: "tenants",
Attributes: &app.TenantAttributes{
CreatedAt: &tenantCreated,
Email: strToPtr("[email protected]"),
Profile: strToPtr("Q X"),
Namespaces: []*app.NamespaceAttributes{
{
CreatedAt: &ns1Time,
UpdatedAt: &ns1Time,
ClusterURL: strToPtr("http://test1.org"),
ClusterAppDomain: strToPtr("apps.example.com"),
ClusterConsoleURL: strToPtr("https://console.example.com/console"),
ClusterMetricsURL: strToPtr("https://metrics.example.com"),
ClusterLoggingURL: strToPtr("https://console.example.com/console"),
Name: strToPtr("test-che"),
Type: strToPtr("che"),
Version: strToPtr("1.0"),
State: strToPtr("created"),
ClusterCapacityExhausted: boolToPtr(true),
},
{
CreatedAt: &ns2Time,
UpdatedAt: &ns2Time,
ClusterURL: strToPtr("http://test2.org"),
ClusterAppDomain: strToPtr("apps.example.com"),
ClusterConsoleURL: strToPtr("https://console.example.com/console"),
ClusterMetricsURL: strToPtr("https://metrics.example.com"),
ClusterLoggingURL: strToPtr("https://console.example.com/console"),
Name: strToPtr("test-jenkins"),
Type: strToPtr("jenkins"),
Version: strToPtr("1.0"),
State: strToPtr("created"),
ClusterCapacityExhausted: boolToPtr(true),
},
},
},
}

got := convertTenant(ctx, tenant, namespaces, resolveCluster)
require.Equal(t, want, got)
}

func strToPtr(s string) *string {
return &s
}

func boolToPtr(b bool) *bool {
return &b
}
Loading

0 comments on commit 9c2ea27

Please sign in to comment.