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
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ app/node_modules
bin
deploy
docs
plugins/*/lib
plugins/*/lib-esm
plugins/*/node_modules
3 changes: 1 addition & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.15
go-version: 1.16

- name: React UI
run: |
cd ./app
yarn install
yarn lint
yarn build
Expand Down
35 changes: 29 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
# Binaries
bin
# dependencies
node_modules
/.pnp
.pnp.js

# Temporary files for code generation
tmp
# testing
/coverage

# application.yaml which contains a list of Application CRs for local testing.
application.yaml
# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

# lib
lib
lib-esm

# build
/app/build

# binaries
/bin
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ cd deploy/docker && docker-compose up

# Without Docker Compose
docker build -f ./cmd/kobs/Dockerfile -t kobsio/kobs:dev .
docker run -it --rm --name kobs -p 15219:15219 -p 15220:15220 -p 15221:15221 -v $(pwd)/config.yaml:/kobs/config.yaml -v $HOME/.kube/config:/.kube/config kobsio/kobs:dev
docker run -it --rm --name kobs -p 15219:15219 -p 15220:15220 -p 15221:15221 -v $(pwd)/deploy/docker/kobs/config.yaml:/kobs/config.yaml -v $HOME/.kube/config:/.kube/config kobsio/kobs:dev --development
docker run -it --rm --name envoy -p 15222:15222 -v $(pwd)/deploy/docker/envoy/envoy.yaml:/etc/envoy/envoy.yaml:ro envoyproxy/envoy:v1.17.0
```

Expand Down
41 changes: 41 additions & 0 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "app",
"version": "0.0.0",
"private": true,
"proxy": "http://localhost:15220",
"dependencies": {
"@kobsio/plugin-core": "*",
"@kobsio/plugin-resources": "*",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"typescript": "^4.1.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Binary file added app/public/favicon.ico
Binary file not shown.
40 changes: 40 additions & 0 deletions app/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Kubernetes Observability Platform" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>kobs</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Binary file added app/public/logo192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/public/logo512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions app/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
3 changes: 3 additions & 0 deletions app/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
16 changes: 16 additions & 0 deletions app/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom';

// Import plugins. Here we import all plugins, which we want to add to the current kobs app. By default this are all
// first party plugins from the /plugins folder.
import { App } from '@kobsio/plugin-core';
import resourcesPlugin from '@kobsio/plugin-resources';

ReactDOM.render(
<React.StrictMode>
<App plugins={{
...resourcesPlugin,
}} />
</React.StrictMode>,
document.getElementById('root')
);
1 change: 1 addition & 0 deletions app/src/react-app-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="react-scripts" />
19 changes: 19 additions & 0 deletions app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "../tsconfig.json",
"include": ["src"],
"compilerOptions": {
"baseUrl": "src",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}
}
27 changes: 27 additions & 0 deletions cmd/kobs/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM --platform=linux/amd64 node:14 as app
WORKDIR /kobs
COPY lerna.json package.json tsconfig.json typings.d.ts yarn.lock /kobs/
COPY app /kobs/app
COPY plugins /kobs/plugins
RUN yarn install --frozen-lockfile
RUN yarn build

FROM golang:1.16.5-alpine3.13 as api
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "Building on $BUILDPLATFORM, for $TARGETPLATFORM" > /log
RUN apk update && apk add git make
WORKDIR /kobs
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN make build

FROM alpine:3.13.0
RUN apk update && apk add --no-cache ca-certificates
RUN mkdir /kobs
COPY --from=app /kobs/app/build /kobs/app/build
COPY --from=api /kobs/bin/kobs /kobs
WORKDIR /kobs
USER nobody
ENTRYPOINT [ "/kobs/kobs" ]
139 changes: 139 additions & 0 deletions cmd/kobs/kobs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package main

import (
"fmt"
"os"
"os/signal"
"syscall"

"github.com/kobsio/kobs/pkg/api"
"github.com/kobsio/kobs/pkg/app"
"github.com/kobsio/kobs/pkg/config"
"github.com/kobsio/kobs/pkg/metrics"
"github.com/kobsio/kobs/pkg/version"

"github.com/sirupsen/logrus"
flag "github.com/spf13/pflag"
)

var (
log = logrus.WithFields(logrus.Fields{"package": "main"})
configFile string
isDevelopment bool
logFormat string
logLevel string
showVersion bool
)

// init is used to define all flags for kobs. If a specific package needs some additional flags, they must be defined in
// the init method of the package. See the pkg/metrics/metrics.go file, which defines an additional metrics.address flag
// for the metrics server. All package specific flags should be prefixed with the name of the package.
func init() {
defaultConfigFile := "config.yaml"
if os.Getenv("KOBS_CONFIG") != "" {
defaultConfigFile = os.Getenv("KOBS_CONFIG")
}

defaultLogFormat := "plain"
if os.Getenv("KOBS_LOG_FORMAT") != "" {
defaultLogFormat = os.Getenv("KOBS_LOG_FORMAT")
}

defaultLogLevel := "info"
if os.Getenv("KOBS_LOG_LEVEL") != "" {
defaultLogLevel = os.Getenv("KOBS_LOG_LEVEL")
}

flag.StringVar(&configFile, "config", defaultConfigFile, "Name of the configuration file.")
flag.BoolVar(&isDevelopment, "development", false, "Use development version.")
flag.StringVar(&logFormat, "log.format", defaultLogFormat, "Set the output format of the logs. Must be \"plain\" or \"json\".")
flag.StringVar(&logLevel, "log.level", defaultLogLevel, "Set the log level. Must be \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\" or \"panic\".")
flag.BoolVar(&showVersion, "version", false, "Print version information.")
}

func main() {
flag.Parse()

// Configure our logging library. The logs can be written in plain format (the plain format is compatible with
// logfmt) or in json format. The default is plain, because it is better to read during development. In a production
// environment you should consider to use json, so that the logs can be parsed by a logging system like
// Elasticsearch.
// Next to the log format it is also possible to configure the log leven. The accepted values are "trace", "debug",
// "info", "warn", "error", "fatal" and "panic". The default log level is "info". When the log level is set to
// "trace" or "debug" we will also print the caller in the logs.
if logFormat == "json" {
logrus.SetFormatter(&logrus.JSONFormatter{})
} else {
logrus.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
}

lvl, err := logrus.ParseLevel(logLevel)
if err != nil {
log.WithError(err).WithFields(logrus.Fields{"log.level": logLevel}).Fatal("Could not set log level")
}
logrus.SetLevel(lvl)

if lvl == logrus.TraceLevel || lvl == logrus.DebugLevel {
logrus.SetReportCaller(true)
}

// Load the configuration for kobs from the provided configuration file.
cfg, err := config.Load(configFile)
if err != nil {
log.WithError(err).WithFields(logrus.Fields{"config": configFile}).Fatalf("Could not load configuration file.")
}

// When the version value is set to "true" (--version) we will print the version information for kobs. After we
// printed the version information the application is stopped.
// The short form of the version information is also printed in two lines, when the version option is set to
// "false".
if showVersion {
v, err := version.Print("kobs")
if err != nil {
log.WithError(err).Fatalf("Failed to print version information")
}

fmt.Fprintln(os.Stdout, v)
return
}

log.WithFields(version.Info()).Infof("Version information")
log.WithFields(version.BuildContext()).Infof("Build context")

// Initialize each component and start it in it's own goroutine, so that the main goroutine is only used as listener
// for terminal signals, to initialize the graceful shutdown of the components.
// The appServer is the kobs application server, which serves the React frontend and the health endpoint. The
// metrics server is used to serve the kobs metrics.
apiServer, err := api.New(cfg, isDevelopment)
if err != nil {
log.WithError(err).Fatalf("Could not create API server.")
}
go apiServer.Start()

appServer, err := app.New(isDevelopment)
if err != nil {
log.WithError(err).Fatalf("Could not create Application server.")
}
go appServer.Start()

metricsServer := metrics.New()
go metricsServer.Start()

// All components should be terminated gracefully. For that we are listen for the SIGINT and SIGTERM signals and try
// to gracefully shutdown the started kobs components. This ensures that established connections or tasks are not
// interrupted.
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

log.Debugf("Start listining for SIGINT and SIGTERM signal.")
<-done
log.Debugf("Start shutdown process.")

metricsServer.Stop()
appServer.Stop()
apiServer.Stop()

log.Infof("Shutdown kobs...")
}
Loading