Skip to content

Commit

Permalink
Merge pull request #4218 from utkarsh-pro/utkarsh-pro/feature/multi-c…
Browse files Browse the repository at this point in the history
…ontext-support

Multi-Context Support
  • Loading branch information
Revolyssup committed Feb 13, 2022
2 parents bfb387d + 9ab1e2d commit f2ee7b7
Show file tree
Hide file tree
Showing 36 changed files with 4,405 additions and 5,966 deletions.
25 changes: 16 additions & 9 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
"path"
"time"

"github.com/gofrs/uuid"
"github.com/layer5io/meshery/handlers"
"github.com/layer5io/meshery/helpers"
"github.com/layer5io/meshery/internal/graphql"
"github.com/layer5io/meshery/internal/graphql/model"
"github.com/layer5io/meshery/internal/store"
"github.com/layer5io/meshery/models"
"github.com/layer5io/meshery/models/pattern/core"
Expand All @@ -22,7 +22,6 @@ import (
"github.com/layer5io/meshkit/database"
"github.com/layer5io/meshkit/logger"
"github.com/layer5io/meshkit/utils/broadcast"
mesherykube "github.com/layer5io/meshkit/utils/kubernetes"
meshsyncmodel "github.com/layer5io/meshsync/pkg/model"
"github.com/spf13/viper"

Expand All @@ -49,6 +48,12 @@ func main() {
models.GlobalTokenForAnonymousResults = globalTokenForAnonymousResults
}

instanceID, err := uuid.NewV4()
if err != nil {
logrus.Error(err)
os.Exit(1)
}

// Initialize Logger instance
log, err := logger.New("meshery", logger.Options{
Format: logger.SyslogLogFormat,
Expand All @@ -73,6 +78,8 @@ func main() {
viper.SetDefault("OS", "meshery")
viper.SetDefault("COMMITSHA", commitsha)
viper.SetDefault("RELEASE_CHANNEL", releasechannel)
viper.SetDefault("INSTANCE_ID", &instanceID)

viper.SetDefault("SKIP_DOWNLOAD_CONTENT", false)
viper.SetDefault("SKIP_COMP_GEN", false)
store.Initialize()
Expand Down Expand Up @@ -148,7 +155,6 @@ func main() {
logrus.Fatal(err)
}

kubeclient := mesherykube.Client{}
meshsyncCh := make(chan struct{})
brokerConn := nats.NewEmptyConnection

Expand All @@ -167,6 +173,7 @@ func main() {
&models.UserPreference{},
&models.PerformanceTestConfig{},
&models.SmiResultWithID{},
models.K8sContext{},
)
if err != nil {
logrus.Fatal(err)
Expand All @@ -183,6 +190,7 @@ func main() {
MesheryFilterPersister: &models.MesheryFilterPersister{DB: &dbHandler},
MesheryApplicationPersister: &models.MesheryApplicationPersister{DB: &dbHandler},
MesheryPatternResourcePersister: &models.PatternResourcePersister{DB: &dbHandler},
MesheryK8sContextPersister: &models.MesheryK8sContextPersister{DB: &dbHandler},
GenericPersister: dbHandler,
}
lProv.Initialize()
Expand Down Expand Up @@ -226,7 +234,6 @@ func main() {
Queue: mainQueue,

KubeConfigFolder: viper.GetString("KUBECONFIG_FOLDER"),
KubeClient: &kubeclient,

GrafanaClient: models.NewGrafanaClient(),
GrafanaClientForQuery: models.NewGrafanaClientWithHTTPClient(&http.Client{Timeout: time.Second}),
Expand Down Expand Up @@ -277,11 +284,11 @@ func main() {

// only uninstalls meshery-operator using helm charts
// useful for dev deployments
logrus.Info("Uninstalling meshery-operator...")
err = model.Initialize(&kubeclient, true, adapterTracker)
if err != nil {
log.Error(err)
}
// logrus.Info("Uninstalling meshery-operator...")
// err = model.Initialize(&kubeclient, true, adapterTracker)
// if err != nil {
// log.Error(err)
// }

logrus.Info("Shutting down Meshery")
}
20 changes: 7 additions & 13 deletions handlers/content_modifier.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package handlers

import (
"context"
"encoding/json"
"sync"

"github.com/layer5io/meshery/models"
"github.com/layer5io/meshery/models/pattern/core"
meshkube "github.com/layer5io/meshkit/utils/kubernetes"
"gopkg.in/yaml.v2"
)

Expand All @@ -32,7 +32,7 @@ func NewContentModifier(token string,

//TODO: Similar mechanisms for filters and applications
//Takes in response bytes, and add metadata to it based on some checks
func (mc *ContentModifier) AddMetadataForPatterns(contentBytes *[]byte) error {
func (mc *ContentModifier) AddMetadataForPatterns(ctx context.Context, contentBytes *[]byte) error {
var patternsPage models.MesheryPatternPage
err := json.Unmarshal(*contentBytes, &patternsPage)
if err != nil {
Expand Down Expand Up @@ -63,7 +63,7 @@ func (mc *ContentModifier) AddMetadataForPatterns(contentBytes *[]byte) error {
if err != nil {
return
}
msg, ok := mc.isPatternSupported(patterncontent)
msg, ok := mc.isPatternSupported(ctx, patterncontent)
(*p)[i]["canSupport"] = ok
(*p)[i]["errmsg"] = msg
}(pattern, i, &p, mc.token, mc.provider, mc.prefObj, mc.userID)
Expand All @@ -78,7 +78,7 @@ func (mc *ContentModifier) AddMetadataForPatterns(contentBytes *[]byte) error {
}

//takes a patternfile and returns the status of its current support by using dry run
func (mc *ContentModifier) isPatternSupported(patternfile string) (msg string, ok bool) {
func (mc *ContentModifier) isPatternSupported(ctx context.Context, patternfile string) (msg string, ok bool) {
var pattern map[string]interface{}
err := yaml.Unmarshal([]byte(patternfile), &pattern)
if err != nil {
Expand All @@ -88,19 +88,12 @@ func (mc *ContentModifier) isPatternSupported(patternfile string) (msg string, o
if err != nil {
return err.Error(), false
}
if mc.prefObj == nil || mc.prefObj.K8SConfig == nil || mc.prefObj.K8SConfig.Config == nil {
return "could not detect kube config from preference", false
}
kc, err := meshkube.New(mc.prefObj.K8SConfig.Config) //possible nil dereference
if err != nil {
return err.Error(), false
}

msg, err = _processPattern(
mc.token,
ctx,
mc.provider,
patternFile,
mc.prefObj,
kc,
mc.userID,
false,
true,
Expand All @@ -109,5 +102,6 @@ func (mc *ContentModifier) isPatternSupported(patternfile string) (msg string, o
if err != nil {
return err.Error(), false
}

return msg, true
}
111 changes: 111 additions & 0 deletions handlers/contexts_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package handlers

import (
"encoding/json"
"net/http"

"github.com/gorilla/mux"
"github.com/layer5io/meshery/models"
)

func (h *Handler) GetAllContexts(w http.ResponseWriter, req *http.Request, prefObj *models.Preference, user *models.User, provider models.Provider) {
token, ok := req.Context().Value(models.TokenCtxKey).(string)
if !ok {
http.Error(w, "failed to get token", http.StatusInternalServerError)
return
}

q := req.URL.Query()

vals, err := provider.GetK8sContexts(token, q.Get("page"), q.Get("pageSize"), q.Get("search"), q.Get("order"))
if err != nil {
http.Error(w, "failed to get contexts", http.StatusInternalServerError)
return
}

if err := json.NewEncoder(w).Encode(vals); err != nil {
http.Error(w, "failed to encode contexts", http.StatusInternalServerError)
return
}
}

func (h *Handler) GetContext(w http.ResponseWriter, req *http.Request, prefObj *models.Preference, user *models.User, provider models.Provider) {
if req.URL.Query().Get("current") != "" {
context, ok := req.Context().Value(models.KubeContextKey).(*models.K8sContext)
if !ok || context == nil {
http.Error(w, "failed to get context", http.StatusInternalServerError)
return
}

if err := json.NewEncoder(w).Encode(context); err != nil {
http.Error(w, "failed to encode context", http.StatusInternalServerError)
return
}

return
}

token, ok := req.Context().Value(models.TokenCtxKey).(string)
if !ok {
http.Error(w, "failed to get token", http.StatusInternalServerError)
return
}

val, err := provider.GetK8sContext(token, mux.Vars(req)["id"])
if err != nil {
http.Error(w, "failed to get context", http.StatusInternalServerError)
return
}

if err := json.NewEncoder(w).Encode(val); err != nil {
http.Error(w, "failed to encode context", http.StatusInternalServerError)
return
}
}

func (h *Handler) DeleteContext(w http.ResponseWriter, req *http.Request, prefObj *models.Preference, user *models.User, provider models.Provider) {
token, ok := req.Context().Value(models.TokenCtxKey).(string)
if !ok {
http.Error(w, "failed to get token", http.StatusInternalServerError)
return
}

_, err := provider.DeleteK8sContext(token, mux.Vars(req)["id"])
if err != nil {
http.Error(w, "failed to delete context", http.StatusInternalServerError)
return
}
}

func (h *Handler) GetCurrentContextHandler(w http.ResponseWriter, req *http.Request, prefObj *models.Preference, user *models.User, provider models.Provider) {
token, ok := req.Context().Value(models.TokenCtxKey).(string)
if !ok {
http.Error(w, "failed to get token", http.StatusInternalServerError)
return
}

val, err := h.GetCurrentContext(token, provider)
if err != nil {
http.Error(w, "failed to get current context", http.StatusInternalServerError)
return
}

if err := json.NewEncoder(w).Encode(val); err != nil {
http.Error(w, "failed to encode context", http.StatusInternalServerError)
return
}
}

func (h *Handler) SetCurrentContextHandler(w http.ResponseWriter, req *http.Request, prefObj *models.Preference, user *models.User, provider models.Provider) {
token, ok := req.Context().Value(models.TokenCtxKey).(string)
if !ok {
http.Error(w, "failed to get token", http.StatusInternalServerError)
return
}

_, err := provider.SetCurrentContext(token, mux.Vars(req)["id"])
if err != nil {
http.Error(w, "failed to set current context", http.StatusInternalServerError)
return
}
}
4 changes: 2 additions & 2 deletions handlers/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,14 @@ type adapterParamsWrapper struct {
// swagger:response k8sConfigRespWrapper
type k8sConfigRespWrapper struct {
// in: body
Body *models.K8SConfig
// Body *models.K8SConfig
}

// Returns kubernetes context list
// swagger:response k8sContextsRespWrapper
type k8sContextsRespWrapper struct {
// in: body
Body []*models.K8SContext
// Body []*models.K8SContext
}

// Parameters for updating provider choice
Expand Down
41 changes: 29 additions & 12 deletions handlers/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,26 @@ const (
ErrDecodePatternCode = "2169"
ErrParsePatternCode = "2170"
ErrConvertPatternCode = "2171"
ErrMesheryInstanceIDCode = "2173"
ErrInvalidKubeConfigCode = "2174"
ErrInvalidKubeHandlerCode = "2175"
ErrInvalidKubeContextCode = "2176"
)

var (
ErrInvalidK8SConfig = errors.New(ErrInvalidK8SConfigCode, errors.Alert, []string{"No valid kubernetes config found"}, []string{"Kubernetes config is not initialized with Meshery"}, []string{"Kubernetes config is not accessible to meshery or not valid"}, []string{"Upload your kubernetes config via the settings dashboard. If uploaded, wait for a minute for it to get initialized"})
ErrNilClient = errors.New(ErrNilClientCode, errors.Alert, []string{"Kubernetes client not initialized"}, []string{"Kubernetes config is not initialized with Meshery"}, []string{"Kubernetes config is not accessible to meshery or not valid"}, []string{"Upload your kubernetes config via the settings dashboard. If uploaded, wait for a minute for it to get initialized"})
ErrPrometheusConfig = errors.New(ErrPrometheusConfigCode, errors.Alert, []string{"Prometheus endpoint not configured"}, []string{"Cannot find valid Prometheus endpoint in user pref"}, []string{"Prometheus endpoint might not be reachable from meshery"}, []string{"Setup your Prometheus Endpoint via the settings dashboard"})
ErrGrafanaConfig = errors.New(ErrGrafanaConfigCode, errors.Alert, []string{"Grafana endpoint not configured"}, []string{"Cannot find valid grafana endpoint in user pref"}, []string{"Grafana endpoint might not be reachable from meshery"}, []string{"Setup your Grafana Endpoint via the settings dashboard"})
ErrStaticBoards = errors.New(ErrStaticBoardsCode, errors.Alert, []string{"unable to get static board"}, []string{"unable to get static board"}, []string{"No boards could be available in grafana"}, []string{})
ErrValidAdapter = errors.New(ErrValidAdapterCode, errors.Alert, []string{"Unable to find valid Adapter URL"}, []string{"unable to find a valid adapter for the given adapter URL"}, []string{"Given adapter URL is not valid"}, []string{"Please provide a valid Adapter URL"})
ErrAddAdapter = errors.New(ErrAddAdapterCode, errors.Alert, []string{"meshLocationURL is empty"}, []string{"meshLocationURL is empty to add an adapter"}, []string{"meshLocationURL cannot be empty to add an adapter"}, []string{"please provide the meshLocationURL"})
ErrMeshClient = errors.New(ErrMeshClientCode, errors.Alert, []string{"Error creating a mesh client", "Error pinging the mesh adapter"}, []string{"Unable to create a mesh client", "Unable to ping the mesh adapter"}, []string{"Adapter could not be pinged"}, []string{"Unable to connect to the Mesh adapter using the given config, please try again"})
ErrWriteResponse = errors.New(ErrWriteResponseCode, errors.Alert, []string{"Error writing response"}, []string{}, []string{}, []string{})
ErrTestConfigs = errors.New(ErrTestConfigsCode, errors.Alert, []string{"Error fetching test configs"}, []string{}, []string{}, []string{})
ErrInvalidGenValue = errors.New(ErrInvalidGenValueCode, errors.Alert, []string{"Invalid value for gen"}, []string{}, []string{}, []string{"please provide a valid value for gen (load generator)"})
ErrParseDuration = errors.New(ErrParseDurationCode, errors.Alert, []string{"error parsing test duration"}, []string{}, []string{"The format of the duration passed could be incorrect"}, []string{"please refer to: https://docs.meshery.io/guides/mesheryctl#performance-management"})
ErrInvalidK8SConfig = errors.New(ErrInvalidK8SConfigCode, errors.Alert, []string{"No valid kubernetes config found"}, []string{"Kubernetes config is not initialized with Meshery"}, []string{"Kubernetes config is not accessible to meshery or not valid"}, []string{"Upload your kubernetes config via the settings dashboard. If uploaded, wait for a minute for it to get initialized"})
ErrNilClient = errors.New(ErrNilClientCode, errors.Alert, []string{"Kubernetes client not initialized"}, []string{"Kubernetes config is not initialized with Meshery"}, []string{"Kubernetes config is not accessible to meshery or not valid"}, []string{"Upload your kubernetes config via the settings dashboard. If uploaded, wait for a minute for it to get initialized"})
ErrPrometheusConfig = errors.New(ErrPrometheusConfigCode, errors.Alert, []string{"Prometheus endpoint not configured"}, []string{"Cannot find valid Prometheus endpoint in user pref"}, []string{"Prometheus endpoint might not be reachable from meshery"}, []string{"Setup your Prometheus Endpoint via the settings dashboard"})
ErrGrafanaConfig = errors.New(ErrGrafanaConfigCode, errors.Alert, []string{"Grafana endpoint not configured"}, []string{"Cannot find valid grafana endpoint in user pref"}, []string{"Grafana endpoint might not be reachable from meshery"}, []string{"Setup your Grafana Endpoint via the settings dashboard"})
ErrStaticBoards = errors.New(ErrStaticBoardsCode, errors.Alert, []string{"unable to get static board"}, []string{"unable to get static board"}, []string{"No boards could be available in grafana"}, []string{})
ErrValidAdapter = errors.New(ErrValidAdapterCode, errors.Alert, []string{"Unable to find valid Adapter URL"}, []string{"unable to find a valid adapter for the given adapter URL"}, []string{"Given adapter URL is not valid"}, []string{"Please provide a valid Adapter URL"})
ErrAddAdapter = errors.New(ErrAddAdapterCode, errors.Alert, []string{"meshLocationURL is empty"}, []string{"meshLocationURL is empty to add an adapter"}, []string{"meshLocationURL cannot be empty to add an adapter"}, []string{"please provide the meshLocationURL"})
ErrMeshClient = errors.New(ErrMeshClientCode, errors.Alert, []string{"Error creating a mesh client", "Error pinging the mesh adapter"}, []string{"Unable to create a mesh client", "Unable to ping the mesh adapter"}, []string{"Adapter could not be pinged"}, []string{"Unable to connect to the Mesh adapter using the given config, please try again"})
ErrWriteResponse = errors.New(ErrWriteResponseCode, errors.Alert, []string{"Error writing response"}, []string{}, []string{}, []string{})
ErrTestConfigs = errors.New(ErrTestConfigsCode, errors.Alert, []string{"Error fetching test configs"}, []string{}, []string{}, []string{})
ErrInvalidGenValue = errors.New(ErrInvalidGenValueCode, errors.Alert, []string{"Invalid value for gen"}, []string{}, []string{}, []string{"please provide a valid value for gen (load generator)"})
ErrParseDuration = errors.New(ErrParseDurationCode, errors.Alert, []string{"error parsing test duration"}, []string{}, []string{"The format of the duration passed could be incorrect"}, []string{"please refer to: https://docs.meshery.io/guides/mesheryctl#performance-management"})
ErrMesheryInstanceID = errors.New(ErrMesheryInstanceIDCode, errors.Alert, []string{"Error: Meshery Instance ID is empty or is invalid"}, []string{}, []string{}, []string{})
)

func ErrPrometheusScan(err error) error {
Expand Down Expand Up @@ -344,6 +349,18 @@ func ErrChangeK8sContext(err error) error {
return errors.New(ErrCreateDirCode, errors.Alert, []string{"Error changing context"}, []string{err.Error()}, []string{"Context Name might be invalid or not present in the uploaded kubeconfig"}, []string{"Check the context name, if the context name is correct and is present in the kubeconfig then try uploading the kubeconfig again"})
}

func ErrInvalidKubeConfig(err error, content string) error {
return errors.New(ErrInvalidKubeConfigCode, errors.Alert, []string{"Invalid Kube Config ", content}, []string{err.Error()}, []string{"Meshery handler failed to find a valid kubernetes config for the deployment"}, []string{"Try uploading a new kubeconfig and also ensure that meshery can reach kubernetes API server"})
}

func ErrInvalidKubeHandler(err error, content string) error {
return errors.New(ErrInvalidKubeHandlerCode, errors.Alert, []string{"Invalid Kube Handler", content}, []string{err.Error()}, []string{"Meshery handler failed to find a valid kubernetes handler for the deployment"}, []string{"Try uploading a new kubeconfig and also ensure that meshery can reach kubernetes API server"})
}

func ErrInvalidKubeContext(err error, content string) error {
return errors.New(ErrInvalidKubeContextCode, errors.Alert, []string{"Invalid Kube Context", content}, []string{err.Error()}, []string{"Meshery handler failed to find a valid kubernetes context for the deployment"}, []string{"Try uploading a new kubeconfig and also ensure that meshery can reach kubernetes API server"})
}

func ErrSavingUserPreference(err error) error {
return errors.New(ErrSavingUserPreferenceCode, errors.Alert, []string{"Error saving user preference."}, []string{err.Error()}, []string{"Invalid data passed", "Unable to connect with provider"}, []string{"Pass valid values for preferences", "Make sure provider supports saving user preferences", "Make sure you're connected with provider", "Make sure extension provides these preferences"})
}
Expand Down

0 comments on commit f2ee7b7

Please sign in to comment.