Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Web Interface #146

Open
zheng1 opened this issue Mar 1, 2022 · 2 comments
Open

Support Web Interface #146

zheng1 opened this issue Mar 1, 2022 · 2 comments
Labels
kind/feature Categorizes issue or PR as related to a new feature.

Comments

@zheng1
Copy link
Member

zheng1 commented Mar 1, 2022

What would you like to be added:

Provide a web interface that allows users to view results directly through a browser

Why is this needed:

The pure CLI view of the inspect results is not easy to visualize, it is easier to understand the visual results through the web page, and it can be increased for the inspection and solution of the results.

@zheng1 zheng1 added the kind/feature Categorizes issue or PR as related to a new feature. label Mar 1, 2022
@zheng1
Copy link
Member Author

zheng1 commented Mar 1, 2022

Proposal

How to build a web server

Sample code: https://github.com/zheng1/kubeeye/tree/dev-web/web

First we build a static file server for the front-end

//go:embed dist/*
var assets embed.FS

func RunWebService(ctx context.Context) error {
	subFS, _ := fs.Sub(assets, "dist")
	assetsFs := http.FileServer(http.FS(subFS))
	mux := http.NewServeMux()
	mux.Handle("/", assetsFs)
	return http.ListenAndServe(":8000", mux)
}

Then we forward the API to the kube-apiserver

type errorResponder struct{}

func (e *errorResponder) Error(w http.ResponseWriter, req *http.Request, err error) {
	klog.Error(err)
	responsewriters.InternalError(w, req, err)
}

func loadConfig() (*rest.Config, error) {
	config, err := rest.InClusterConfig()
	if err == nil {
		return config, nil
	}
	return clientcmd.BuildConfigFromFlags("", os.Getenv("HOME")+"/.kube/config")

}

func RunWebService(ctx context.Context) error {
	config, err := loadConfig()
	if err != nil {
		return err
	}

	kubernetes, _ := url.Parse(config.Host)
	defaultTransport, err := rest.TransportFor(config)
	if err != nil {
		return err
	}

	var handleKubeAPIfunc = func(w http.ResponseWriter, req *http.Request) {
		klog.Info(req.URL)
		s := *req.URL
		s.Host = kubernetes.Host
		s.Scheme = kubernetes.Scheme

		// make sure we don't override kubernetes's authorization
		req.Header.Del("Authorization")
		httpProxy := proxy.NewUpgradeAwareHandler(&s, defaultTransport, true, false, &errorResponder{})
		httpProxy.UpgradeTransport = proxy.NewUpgradeRequestRoundTripper(defaultTransport, defaultTransport)
		httpProxy.ServeHTTP(w, req)
		return
	}

	mux := http.NewServeMux()
	mux.HandleFunc("/apis/", handleKubeAPIfunc)
	mux.HandleFunc("/api/", handleKubeAPIfunc)

	return http.ListenAndServe(":8000", mux)
}

In this way we only need to put the relative index.html and js and css files in the dist folder.

https://parceljs.org/ is a blazing fast javascript packer!

"dev": "parcel",
"build": "parcel build"

Development

Run yarn dev and another terminal run go run ./cmd/web/ you can start a dev environment, and open http://localhost:1234 to see result

WechatIMG70

Here is just an example, we have listed all the namespaces in the cluster in the code.

kubeeye/web/src/App.js

Lines 6 to 33 in ce7ddab

export function App() {
const [namespaces, setNamespaces] = useState({});
useEffect(() => {
getNamespaces().then(function (nss) {
setNamespaces(nss)
})
}, []);
const columns = [{
title: 'Name',
dataIndex: 'metadata.name',
}, {
title: 'Create Time',
dataIndex: 'metadata.creationTimestamp',
}, {
title: 'Status',
dataIndex: 'status.phase',
}]
if (Object.keys(namespaces).length === 0) {
return <Loading/>
}
return (
<div>
<Table rowKey="metadata.name" columns={columns} dataSource={namespaces}/>
</div>
);

export function getNamespaces() {
return axios.get(`/api/v1/namespaces`)
.then(res => {
return res.data.items
})
}

In the following configuration, port 1234 will proxy k8s request to port 8000

kubeeye/web/.proxyrc

Lines 2 to 7 in ce7ddab

"/api": {
"target": "http://localhost:8000/"
},
"/apis": {
"target": "http://localhost:8000/"
}

Production

Run yarn build and go run ./cmd/web/, and open http://localhost:8000, you can see the same result in pure go without other process.

@zheng1
Copy link
Member Author

zheng1 commented Mar 3, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature Categorizes issue or PR as related to a new feature.
Projects
None yet
Development

No branches or pull requests

1 participant