Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan
- [#93](https://github.com/kobsio/kobs/pull/93): Show status of Kubernetes resource in the table of the resources plugin.
- [#97](https://github.com/kobsio/kobs/pull/97): Add support for Kiali metrics.
- [#98](https://github.com/kobsio/kobs/pull/98): Add terminal support for Kubernetes Pods.
- [#100](https://github.com/kobsio/kobs/pull/100): Add support for Ephemeral Containers.

### Fixed

Expand Down
6 changes: 3 additions & 3 deletions cmd/kobs/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"github.com/kobsio/kobs/cmd/kobs/plugins"
"github.com/kobsio/kobs/pkg/api/clusters"

"gopkg.in/yaml.v2"
"sigs.k8s.io/yaml"
)

// Config is the complete configuration for kobs.
type Config struct {
Clusters clusters.Config `yaml:"clusters"`
Plugins plugins.Config `yaml:"plugins"`
Clusters clusters.Config `json:"clusters"`
Plugins plugins.Config `json:"plugins"`
}

// Load the configuration for kobs. Most of the configuration options are available as command-line flag, but we also
Expand Down
22 changes: 11 additions & 11 deletions cmd/kobs/plugins/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ import (

// Config holds the configuration for all plugins. We have to add the configuration for all the imported plugins.
type Config struct {
Applications applications.Config `yaml:"applications"`
Resources resources.Config `yaml:"resources"`
Teams teams.Config `yaml:"teams"`
Dashboards dashboards.Config `yaml:"dashboards"`
Prometheus prometheus.Config `yaml:"prometheus"`
Elasticsearch elasticsearch.Config `yaml:"elasticsearch"`
Jaeger jaeger.Config `yaml:"jaeger"`
Markdown markdown.Config `yaml:"markdown"`
Kiali kiali.Config `yaml:"kiali"`
Opsgenie opsgenie.Config `yaml:"opsgenie"`
RSS rss.Config `yaml:"rss"`
Applications applications.Config `json:"applications"`
Resources resources.Config `json:"resources"`
Teams teams.Config `json:"teams"`
Dashboards dashboards.Config `json:"dashboards"`
Prometheus prometheus.Config `json:"prometheus"`
Elasticsearch elasticsearch.Config `json:"elasticsearch"`
Jaeger jaeger.Config `json:"jaeger"`
Markdown markdown.Config `json:"markdown"`
Kiali kiali.Config `json:"kiali"`
Opsgenie opsgenie.Config `json:"opsgenie"`
RSS rss.Config `json:"rss"`
}

// Router implements the router for the plugins package. This only registeres one route which is used to return all the
Expand Down
2 changes: 2 additions & 0 deletions deploy/demo/kind-with-registry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: kobs-demo
featureGates:
EphemeralContainers: true
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${reg_port}"]
Expand Down
1 change: 1 addition & 0 deletions docs/configuration/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,4 @@ plugins:
| forbidden | []string | A list of resources, which can not be retrieved via the kobs API. | No |
| webSocket.address | string | The address, which should be used for the WebSocket connection. By default this will be the current host, but it can be overwritten for development purposes. | No |
| webSocket.allowAllOrigins | boolean | When this is `true`, WebSocket connections are allowed for all origins. This should only be used for development. | No |
| ephemeralContainers | [[]EphemeralContainer](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#ephemeralcontainer-v1-core) | A list of templates for Ephemeral Containers, which can be used to [debug running pods](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-running-pod/#ephemeral-container). | No |
6 changes: 3 additions & 3 deletions docs/contributing/using-the-kobsio-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ import (

// Config holds the configuration for all plugins. We have to add the configuration for all the imported plugins.
type Config struct {
Resources resources.Config `yaml:"resources"`
HelloWorld helloworld.Config `yaml:"helloworld"`
+ MyNewPlugin mynewplugin.Config `yaml:"myNewPlugin"`
Resources resources.Config `json:"resources"`
HelloWorld helloworld.Config `json:"helloworld"`
+ MyNewPlugin mynewplugin.Config `json:"myNewPlugin"`
}

// Router implements the router for the plugins package. This only registeres one route which is used to return all the
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ require (
github.com/prometheus/common v0.30.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/pflag v1.0.5
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.21.3
k8s.io/apiextensions-apiserver v0.21.3
k8s.io/apimachinery v0.21.3
k8s.io/client-go v0.21.3
sigs.k8s.io/yaml v1.2.0
)
14 changes: 12 additions & 2 deletions pkg/api/clusters/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,18 @@ func (c *Cluster) PatchResource(ctx context.Context, namespace, name, path, reso

// CreateResource can be used to create the given resource. The resource is identified by the Kubernetes API path and the
// name of the resource.
func (c *Cluster) CreateResource(ctx context.Context, namespace, path, resource string, body []byte) error {
_, err := c.clientset.RESTClient().Post().AbsPath(path).Namespace(namespace).Resource(resource).Body(body).DoRaw(ctx)
func (c *Cluster) CreateResource(ctx context.Context, namespace, name, path, resource, subResource string, body []byte) error {
if name != "" && subResource != "" {
_, err := c.clientset.RESTClient().Put().AbsPath(path).Namespace(namespace).Name(name).Resource(resource).SubResource(subResource).Body(body).DoRaw(ctx)
if err != nil {
log.WithError(err).WithFields(logrus.Fields{"cluster": c.name, "namespace": namespace, "name": name, "path": path, "resource": resource, "subResource": subResource}).Errorf("CreateResource")
return err
}

return nil
}

_, err := c.clientset.RESTClient().Post().AbsPath(path).Namespace(namespace).Resource(resource).SubResource(subResource).Body(body).DoRaw(ctx)
if err != nil {
log.WithError(err).WithFields(logrus.Fields{"cluster": c.name, "namespace": namespace, "path": path, "resource": resource}).Errorf("CreateResource")
return err
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/clusters/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func init() {
// Config is the configuration required to load all clusters. It takes an array of providers, which are defined in the
// providers package.
type Config struct {
Providers []provider.Config `yaml:"providers"`
Providers []provider.Config `json:"providers"`
}

// TODO
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/clusters/provider/incluster/incluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var (

// Config is the configuration for the InCluster provider.
type Config struct {
Name string `yaml:"name"`
Name string `json:"name"`
}

// GetCluster returns the cluster, where kobs is running in via the incluster configuration. For the selection of the
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/clusters/provider/kubeconfig/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var (

// Config is the configuration for the Kubeconfig provider.
type Config struct {
Path string `yaml:"path"`
Path string `json:"path"`
}

// GetClusters returns all clusters from a given Kubeconfig file. For that the user have to provide the path to the
Expand Down
6 changes: 3 additions & 3 deletions pkg/api/clusters/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ const (
// Config is the provider configuration to get Kubernetes clusters from. The provider configuration only contains the
// provider type and a provider specific configuration.
type Config struct {
Provider Type `yaml:"provider"`
InCluster incluster.Config `yaml:"incluster"`
Kubeconfig kubeconfig.Config `yaml:"kubeconfig"`
Provider Type `json:"provider"`
InCluster incluster.Config `json:"incluster"`
Kubeconfig kubeconfig.Config `json:"kubeconfig"`
}

// GetClusters returns all clusters for the given provider. When the provider field doesn't match our custom Type, we
Expand Down
16 changes: 10 additions & 6 deletions plugins/applications/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ var (

// Config is the structure of the configuration for the applications plugin.
type Config struct {
TopologyCacheDuration time.Duration `yaml:"topologyCacheDuration"`
TeamsCacheDuration time.Duration `yaml:"teamsCacheDuration"`
TopologyCacheDuration string `json:"topologyCacheDuration"`
TeamsCacheDuration string `json:"teamsCacheDuration"`
}

// Router implements the router for the resources plugin, which can be registered in the router for our rest api.
Expand Down Expand Up @@ -209,15 +209,19 @@ func Register(clusters *clusters.Clusters, plugins *plugin.Plugins, config Confi
})

var topology topology.Cache
topology.CacheDuration = config.TopologyCacheDuration
if topology.CacheDuration.Seconds() < 60 {
topologyCacheDuration, err := time.ParseDuration(config.TopologyCacheDuration)
if err != nil || topologyCacheDuration.Seconds() < 60 {
topology.CacheDuration = time.Duration(1 * time.Hour)
} else {
topology.CacheDuration = topologyCacheDuration
}

var teams teams.Cache
teams.CacheDuration = config.TeamsCacheDuration
if teams.CacheDuration.Seconds() < 60 {
teamsCacheDuration, err := time.ParseDuration(config.TeamsCacheDuration)
if err != nil || teamsCacheDuration.Seconds() < 60 {
teams.CacheDuration = time.Duration(1 * time.Hour)
} else {
teams.CacheDuration = teamsCacheDuration
}

router := Router{
Expand Down
14 changes: 7 additions & 7 deletions plugins/elasticsearch/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ var (

// Config is the structure of the configuration for a single Elasticsearch instance.
type Config struct {
Name string `yaml:"name"`
DisplayName string `yaml:"displayName"`
Description string `yaml:"description"`
Address string `yaml:"address"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Token string `yaml:"token"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Address string `json:"address"`
Username string `json:"username"`
Password string `json:"password"`
Token string `json:"token"`
}

// Instance represents a single Elasticsearch instance, which can be added via the configuration file.
Expand Down
14 changes: 7 additions & 7 deletions plugins/jaeger/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ var (

// Config is the structure of the configuration for a single Jaeger instance.
type Config struct {
Name string `yaml:"name"`
DisplayName string `yaml:"displayName"`
Description string `yaml:"description"`
Address string `yaml:"address"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Token string `yaml:"token"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Address string `json:"address"`
Username string `json:"username"`
Password string `json:"password"`
Token string `json:"token"`
}

// ResponseError is the structure for a failed Jaeger API request.
Expand Down
20 changes: 10 additions & 10 deletions plugins/kiali/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ var (

// Config is the structure of the configuration for a single Kiali instance.
type Config struct {
Name string `yaml:"name"`
DisplayName string `yaml:"displayName"`
Description string `yaml:"description"`
Address string `yaml:"address"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Token string `yaml:"token"`
Traffic Traffic `yaml:"traffic"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Address string `json:"address"`
Username string `json:"username"`
Password string `json:"password"`
Token string `json:"token"`
Traffic Traffic `json:"traffic"`
}

// Traffic is the traffic configuration, to set the value to mark a edge as degraded and failure.
type Traffic struct {
Degraded float64 `yaml:"degraded"`
Failure float64 `yaml:"failure"`
Degraded float64 `json:"degraded"`
Failure float64 `json:"failure"`
}

// Graph is the structure of the returned topology graph from Kiali. We have to implement it by ourselve, because we
Expand Down
12 changes: 6 additions & 6 deletions plugins/opsgenie/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ var (

// Config is the structure of the configuration for a single Opsgenie instance.
type Config struct {
Name string `yaml:"name"`
DisplayName string `yaml:"displayName"`
Description string `yaml:"description"`
APIKey string `yaml:"apiKey"`
APIUrl string `yaml:"apiUrl"`
URL string `yaml:"url"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
APIKey string `json:"apiKey"`
APIUrl string `json:"apiUrl"`
URL string `json:"url"`
}

// Instance represents a single Jaeger instance, which can be added via the configuration file.
Expand Down
14 changes: 7 additions & 7 deletions plugins/prometheus/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ var (

// Config is the structure of the configuration for a single Prometheus instance.
type Config struct {
Name string `yaml:"name"`
DisplayName string `yaml:"displayName"`
Description string `yaml:"description"`
Address string `yaml:"address"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Token string `yaml:"token"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Address string `json:"address"`
Username string `json:"username"`
Password string `json:"password"`
Token string `json:"token"`
}

// Instance represents a single Prometheus instance, which can be added via the configuration file.
Expand Down
17 changes: 11 additions & 6 deletions plugins/resources/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/go-chi/render"
"github.com/gorilla/websocket"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
)

// Route is the route under which the plugin should be registered in our router for the rest api.
Expand Down Expand Up @@ -44,14 +45,15 @@ type Resources struct {
// Config is the structure of the configuration for the resources plugin. It only contains one filed to forbid access to
// the provided resources.
type Config struct {
Forbidden []string `yaml:"forbidden"`
WebSocket WebSocket `yaml:"webSocket"`
Forbidden []string `json:"forbidden"`
WebSocket WebSocket `json:"webSocket"`
EphemeralContainers []corev1.EphemeralContainer `json:"ephemeralContainers"`
}

// WebSocket is the structure for the WebSocket configuration for terminal for Pods.
type WebSocket struct {
Address string `yaml:"address"`
AllowAllOrigins bool `yaml:"allowAllOrigins"`
Address string `json:"address"`
AllowAllOrigins bool `json:"allowAllOrigins"`
}

// Router implements the router for the resources plugin, which can be registered in the router for our rest api.
Expand Down Expand Up @@ -239,10 +241,12 @@ func (router *Router) patchResource(w http.ResponseWriter, r *http.Request) {
func (router *Router) createResource(w http.ResponseWriter, r *http.Request) {
clusterName := r.URL.Query().Get("cluster")
namespace := r.URL.Query().Get("namespace")
name := r.URL.Query().Get("name")
resource := r.URL.Query().Get("resource")
subResource := r.URL.Query().Get("subResource")
path := r.URL.Query().Get("path")

log.WithFields(logrus.Fields{"cluster": clusterName, "namespace": namespace, "resource": resource, "path": path}).Tracef("createResource")
log.WithFields(logrus.Fields{"cluster": clusterName, "namespace": namespace, "name": name, "path": path, "resource": resource, "subResource": subResource}).Tracef("createResource")

cluster := router.clusters.GetCluster(clusterName)
if cluster == nil {
Expand All @@ -261,7 +265,7 @@ func (router *Router) createResource(w http.ResponseWriter, r *http.Request) {
return
}

err = cluster.CreateResource(r.Context(), namespace, path, resource, body)
err = cluster.CreateResource(r.Context(), namespace, name, path, resource, subResource, body)
if err != nil {
errresponse.Render(w, r, err, http.StatusBadRequest, "Could not create resource")
return
Expand Down Expand Up @@ -385,6 +389,7 @@ func Register(clusters *clusters.Clusters, plugins *plugin.Plugins, config Confi
var options map[string]interface{}
options = make(map[string]interface{})
options["webSocketAddress"] = config.WebSocket.Address
options["ephemeralContainers"] = config.EphemeralContainers

plugins.Append(plugin.Plugin{
Name: "resources",
Expand Down
Loading