diff --git a/cmd/ui/v1alpha3/main.go b/cmd/ui/v1alpha3/main.go
index d299c6f40f6..1be8ff71856 100644
--- a/cmd/ui/v1alpha3/main.go
+++ b/cmd/ui/v1alpha3/main.go
@@ -6,6 +6,8 @@ import (
"log"
"net/http"
+ _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
+
ui "github.com/kubeflow/katib/pkg/ui/v1alpha3"
)
@@ -26,7 +28,7 @@ func main() {
frontend := http.FileServer(http.Dir(*buildDir))
http.Handle("/katib/", http.StripPrefix("/katib/", frontend))
- http.HandleFunc("/katib/fetch_hp_jobs/", kuh.FetchHPJobs)
+ http.HandleFunc("/katib/fetch_hp_jobs/", kuh.FetchAllHPJobs)
http.HandleFunc("/katib/fetch_nas_jobs/", kuh.FetchNASJobs)
http.HandleFunc("/katib/submit_yaml/", kuh.SubmitYamlJob)
http.HandleFunc("/katib/submit_hp_job/", kuh.SubmitParamsJob)
diff --git a/pkg/ui/v1alpha3/backend.go b/pkg/ui/v1alpha3/backend.go
index 63375e648fe..d9b0aa75779 100644
--- a/pkg/ui/v1alpha3/backend.go
+++ b/pkg/ui/v1alpha3/backend.go
@@ -1,18 +1,16 @@
-package ui
+package v1alpha3
import (
"context"
"encoding/json"
"log"
"net/http"
- "strconv"
"strings"
"time"
"github.com/ghodss/yaml"
"google.golang.org/grpc"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"sigs.k8s.io/controller-runtime/pkg/client"
experimentv1alpha3 "github.com/kubeflow/katib/pkg/apis/controller/experiments/v1alpha3"
@@ -46,29 +44,11 @@ func (k *KatibUIHandler) connectManager() (*grpc.ClientConn, api_pb_v1alpha3.Man
func (k *KatibUIHandler) FetchHPJobs(w http.ResponseWriter, r *http.Request) {
//enableCors(&w)
-
- jobs := make([]JobView, 0)
-
- el, err := k.katibClient.GetExperimentList()
+ jobs, err := k.getExperimentList(consts.DefaultKatibNamespace, JobTypeHP)
if err != nil {
- log.Printf("GetExperimentList for HP failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- for _, experiment := range el.Items {
- if experiment.Spec.Parameters != nil {
- experimentLastCondition, err := experiment.GetLastConditionType()
- if err != nil {
- log.Printf("GetLastConditionType for HP failed: %v", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- jobs = append(jobs, JobView{
- Name: experiment.Name,
- Status: string(experimentLastCondition),
- })
- }
- }
response, err := json.Marshal(jobs)
if err != nil {
@@ -80,40 +60,21 @@ func (k *KatibUIHandler) FetchHPJobs(w http.ResponseWriter, r *http.Request) {
}
-func (k *KatibUIHandler) FetchNASJobs(w http.ResponseWriter, r *http.Request) {
- //enableCors(&w)
-
- jobs := make([]JobView, 0)
-
- el, err := k.katibClient.GetExperimentList()
+// FetchAllHPJobs gets experiments in all namespaces.
+func (k *KatibUIHandler) FetchAllHPJobs(w http.ResponseWriter, r *http.Request) {
+ // Use "" to get experiments in all namespaces.
+ jobs, err := k.getExperimentList("", JobTypeHP)
if err != nil {
- log.Printf("GetExperimentList for NAS failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- for _, experiment := range el.Items {
- if experiment.Spec.NasConfig != nil {
- experimentLastCondition, err := experiment.GetLastConditionType()
- if err != nil {
- log.Printf("GetLastConditionType for HP failed: %v", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- jobs = append(jobs, JobView{
- Name: experiment.Name,
- Status: string(experimentLastCondition),
- })
- }
- }
-
response, err := json.Marshal(jobs)
if err != nil {
- log.Printf("Marshal NAS jobs failed: %v", err)
+ log.Printf("Marshal HP jobs failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(response)
-
}
func (k *KatibUIHandler) SubmitYamlJob(w http.ResponseWriter, r *http.Request) {
@@ -178,7 +139,9 @@ func (k *KatibUIHandler) SubmitParamsJob(w http.ResponseWriter, r *http.Request)
func (k *KatibUIHandler) DeleteExperiment(w http.ResponseWriter, r *http.Request) {
experimentName := r.URL.Query()["experimentName"][0]
- experiment, err := k.katibClient.GetExperiment(experimentName)
+ namespace := r.URL.Query()["namespace"][0]
+
+ experiment, err := k.katibClient.GetExperiment(experimentName, namespace)
if err != nil {
log.Printf("GetExperiment failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -195,12 +158,13 @@ func (k *KatibUIHandler) DeleteExperiment(w http.ResponseWriter, r *http.Request
func (k *KatibUIHandler) FetchHPJobInfo(w http.ResponseWriter, r *http.Request) {
//enableCors(&w)
experimentName := r.URL.Query()["experimentName"][0]
+ namespace := r.URL.Query()["namespace"][0]
conn, c := k.connectManager()
defer conn.Close()
resultText := "trialName"
- experiment, err := k.katibClient.GetExperiment(experimentName)
+ experiment, err := k.katibClient.GetExperiment(experimentName, namespace)
if err != nil {
log.Printf("GetExperiment from HP job failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -272,7 +236,6 @@ func (k *KatibUIHandler) FetchHPJobInfo(w http.ResponseWriter, r *http.Request)
return
}
w.Write(response)
-
}
func (k *KatibUIHandler) FetchHPJobTrialInfo(w http.ResponseWriter, r *http.Request) {
@@ -314,82 +277,6 @@ func (k *KatibUIHandler) FetchHPJobTrialInfo(w http.ResponseWriter, r *http.Requ
w.Write(response)
}
-func (k *KatibUIHandler) FetchNASJobInfo(w http.ResponseWriter, r *http.Request) {
- //enableCors(&w)
- experimentName := r.URL.Query()["experimentName"][0]
-
- responseRaw := make([]NNView, 0)
- var architecture string
- var decoder string
-
- conn, c := k.connectManager()
-
- defer conn.Close()
-
- trials, err := k.katibClient.GetTrialList(experimentName)
- if err != nil {
- log.Printf("GetTrialList from NAS job failed: %v", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- log.Printf("Got Trial List")
-
- for i, t := range trials.Items {
- succeeded := false
- for _, condition := range t.Status.Conditions {
- if condition.Type == trialsv1alpha3.TrialSucceeded {
- succeeded = true
- }
- }
- if succeeded {
- obsLogResp, err := c.GetObservationLog(
- context.Background(),
- &api_pb_v1alpha3.GetObservationLogRequest{
- TrialName: t.Name,
- StartTime: "",
- EndTime: "",
- },
- )
- if err != nil {
- log.Printf("GetObservationLog from NAS job failed: %v", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- metricsName := make([]string, 0)
- metricsValue := make([]string, 0)
- for _, m := range obsLogResp.ObservationLog.MetricLogs {
- metricsName = append(metricsName, m.Metric.Name)
- metricsValue = append(metricsValue, m.Metric.Value)
-
- }
- for _, trialParam := range t.Spec.ParameterAssignments {
- if trialParam.Name == "architecture" {
- architecture = trialParam.Value
- }
- if trialParam.Name == "nn_config" {
- decoder = trialParam.Value
- }
- }
- responseRaw = append(responseRaw, NNView{
- Name: "Generation " + strconv.Itoa(i),
- TrialName: t.Name,
- Architecture: generateNNImage(architecture, decoder),
- MetricsName: metricsName,
- MetricsValue: metricsValue,
- })
- }
- }
- log.Printf("Logs parsed, result: %v", responseRaw)
-
- response, err := json.Marshal(responseRaw)
- if err != nil {
- log.Printf("Marshal result in NAS job failed: %v", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- w.Write(response)
-}
-
// FetchTrialTemplates gets the trial templates for the given namespace.
func (k *KatibUIHandler) FetchTrialTemplates(w http.ResponseWriter, r *http.Request) {
//enableCors(&w)
diff --git a/pkg/ui/v1alpha3/frontend/src/actions/generalActions.js b/pkg/ui/v1alpha3/frontend/src/actions/generalActions.js
index 024f30fb59d..b7b89dede56 100644
--- a/pkg/ui/v1alpha3/frontend/src/actions/generalActions.js
+++ b/pkg/ui/v1alpha3/frontend/src/actions/generalActions.js
@@ -28,16 +28,18 @@ export const DELETE_EXPERIMENT_REQUEST = "DELETE_EXPERIMENT_REQUEST";
export const DELETE_EXPERIMENT_FAILURE = "DELETE_EXPERIMENT_FAILURE";
export const DELETE_EXPERIMENT_SUCCESS = "DELETE_EXPERIMENT_SUCCESS";
-export const deleteExperiment = (experimentName) => ({
+export const deleteExperiment = (name, namespace) => ({
type: DELETE_EXPERIMENT_REQUEST,
- experimentName,
+ name,
+ namespace,
})
export const OPEN_DELETE_EXPERIMENT_DIALOG = "OPEN_DELETE_EXPERIMENT_DIALOG";
-export const openDeleteExperimentDialog = (experimentName) => ({
+export const openDeleteExperimentDialog = (name, namespace) => ({
type: OPEN_DELETE_EXPERIMENT_DIALOG,
- experimentName,
+ name,
+ namespace,
})
export const CLOSE_DELETE_EXPERIMENT_DIALOG = "CLOSE_DELETE_EXPERIMENT_DIALOG";
diff --git a/pkg/ui/v1alpha3/frontend/src/actions/hpCreateActions.js b/pkg/ui/v1alpha3/frontend/src/actions/hpCreateActions.js
index 0aef7c5fecf..33627b05683 100644
--- a/pkg/ui/v1alpha3/frontend/src/actions/hpCreateActions.js
+++ b/pkg/ui/v1alpha3/frontend/src/actions/hpCreateActions.js
@@ -121,6 +121,13 @@ export const changeTrial = (trial) => ({
trial,
})
+export const CHANGE_TRIAL_NAMESPACE_HP = "CHANGE_TRIAL_NAMESPACE_HP";
+
+export const changeTrialNamespace = (namespace) => ({
+ type: CHANGE_TRIAL_NAMESPACE_HP,
+ namespace,
+})
+
export const SUBMIT_HP_JOB_REQUEST = "SUBMIT_HP_JOB_REQUEST";
export const SUBMIT_HP_JOB_SUCCESS = "SUBMIT_HP_JOB_SUCCESS";
export const SUBMIT_HP_JOB_FAILURE = "SUBMIT_HP_JOB_FAILURE";
diff --git a/pkg/ui/v1alpha3/frontend/src/actions/hpMonitorActions.js b/pkg/ui/v1alpha3/frontend/src/actions/hpMonitorActions.js
index 1439e1634c1..9a5de47316e 100644
--- a/pkg/ui/v1alpha3/frontend/src/actions/hpMonitorActions.js
+++ b/pkg/ui/v1alpha3/frontend/src/actions/hpMonitorActions.js
@@ -24,9 +24,10 @@ export const FETCH_HP_JOB_INFO_REQUEST = "FETCH_HP_JOB_INFO_REQUEST";
export const FETCH_HP_JOB_INFO_SUCCESS = "FETCH_HP_JOB_INFO_SUCCESS";
export const FETCH_HP_JOB_INFO_FAILURE = "FETCH_HP_JOB_INFO_FAILURE";
-export const fetchHPJobInfo = (experimentName) => ({
+export const fetchHPJobInfo = (name, namespace) => ({
type: FETCH_HP_JOB_INFO_REQUEST,
- experimentName
+ name,
+ namespace,
})
export const FETCH_HP_JOB_TRIAL_INFO_REQUEST = "FETCH_HP_JOB_TRIAL_INFO_REQUEST";
diff --git a/pkg/ui/v1alpha3/frontend/src/components/App.jsx b/pkg/ui/v1alpha3/frontend/src/components/App.jsx
index dfa35465a20..e2c727f9575 100644
--- a/pkg/ui/v1alpha3/frontend/src/components/App.jsx
+++ b/pkg/ui/v1alpha3/frontend/src/components/App.jsx
@@ -32,7 +32,7 @@ const App = (props) => {
-
+
diff --git a/pkg/ui/v1alpha3/frontend/src/components/HP/Create/HPParameters.jsx b/pkg/ui/v1alpha3/frontend/src/components/HP/Create/HPParameters.jsx
index 3472f39b687..852c952b631 100644
--- a/pkg/ui/v1alpha3/frontend/src/components/HP/Create/HPParameters.jsx
+++ b/pkg/ui/v1alpha3/frontend/src/components/HP/Create/HPParameters.jsx
@@ -175,7 +175,8 @@ const mapStateToProps = (state) => ({
algorithmName: state[module].algorithmName,
algorithmSettings: state[module].algorithmSettings,
parameters: state[module].parameters,
- trial: state[module].trial
+ trial: state[module].trial,
+ trialNamespace: state[module].trialNamespace,
})
//TODO: Added validation and remove it
diff --git a/pkg/ui/v1alpha3/frontend/src/components/HP/Create/Params/Trial.jsx b/pkg/ui/v1alpha3/frontend/src/components/HP/Create/Params/Trial.jsx
index ad031d15afa..fdbb9604fbc 100644
--- a/pkg/ui/v1alpha3/frontend/src/components/HP/Create/Params/Trial.jsx
+++ b/pkg/ui/v1alpha3/frontend/src/components/HP/Create/Params/Trial.jsx
@@ -12,7 +12,7 @@ import Select from '@material-ui/core/Select';
import TextField from '@material-ui/core/TextField';
import { connect } from 'react-redux';
-import { changeTrial } from '../../../../actions/hpCreateActions';
+import { changeTrial, changeTrialNamespace } from '../../../../actions/hpCreateActions';
import { fetchTrialTemplates } from '../../../../actions/templateActions';
const module = "hpCreate";
@@ -44,6 +44,7 @@ class TrialSpecParam extends React.Component {
onTrialNamespaceChange = (event) => {
this.props.fetchTrialTemplates(event.target.value);
+ this.props.changeTrialNamespace(event.target.value);
}
onTrialChange = (event) => {
@@ -118,7 +119,8 @@ const mapStateToProps = state => {
return {
trial: state[module].trial,
templates: state[templateModule].trialTemplates,
+ trialNamespace: state[module].trialNamespace,
}
}
-export default connect(mapStateToProps, { changeTrial, fetchTrialTemplates })(withStyles(styles)(TrialSpecParam));
+export default connect(mapStateToProps, { changeTrialNamespace, changeTrial, fetchTrialTemplates })(withStyles(styles)(TrialSpecParam));
diff --git a/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobInfo.jsx b/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobInfo.jsx
index a358870880f..01653e4d251 100644
--- a/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobInfo.jsx
+++ b/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobInfo.jsx
@@ -33,7 +33,8 @@ const styles = theme => ({
class HPJobInfo extends React.Component {
componentDidMount() {
- this.props.fetchHPJobInfo(this.props.match.params.name);
+ this.props.fetchHPJobInfo(
+ this.props.match.params.name, this.props.match.params.namespace);
}
render () {
@@ -52,6 +53,9 @@ class HPJobInfo extends React.Component {
Experiment Name: {this.props.match.params.name}
+
+ Experiment Namespace: {this.props.match.params.namespace}
+
diff --git a/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobList.jsx b/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobList.jsx
index 5a65ced35d7..6b1b6dd2d89 100644
--- a/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobList.jsx
+++ b/pkg/ui/v1alpha3/frontend/src/components/HP/Monitor/HPJobList.jsx
@@ -43,8 +43,8 @@ const HPJobList = (props) => {
const { classes } = props;
- const onDeleteExperiment = (experimentName) => (event) => {
- props.openDeleteExperimentDialog(experimentName);
+ const onDeleteExperiment = (name, namespace) => (event) => {
+ props.openDeleteExperimentDialog(name, namespace);
}
return (
@@ -64,13 +64,13 @@ const HPJobList = (props) => {
icon = ()
}
return (
-
+
{icon}
-
+
-
+
diff --git a/pkg/ui/v1alpha3/frontend/src/components/Menu/DeleteDialog.jsx b/pkg/ui/v1alpha3/frontend/src/components/Menu/DeleteDialog.jsx
index fbb5c9b3743..71c06833ed7 100644
--- a/pkg/ui/v1alpha3/frontend/src/components/Menu/DeleteDialog.jsx
+++ b/pkg/ui/v1alpha3/frontend/src/components/Menu/DeleteDialog.jsx
@@ -22,7 +22,7 @@ const DeleteDialog = (props) => {
const classes = useStyles();
const onDelete = () => {
- props.deleteExperiment(props.deleteExperimentName);
+ props.deleteExperiment(props.deleteExperimentName, props.deleteExperimentNamespace);
}
return (
@@ -53,6 +53,7 @@ const DeleteDialog = (props) => {
const mapStateToProps = (state) => ({
open: state[module].deleteDialog,
deleteExperimentName: state[module].deleteExperimentName,
+ deleteExperimentNamespace: state[module].deleteExperimentNamespace,
})
export default connect(mapStateToProps, { closeDeleteExperimentDialog, deleteExperiment })(DeleteDialog);
diff --git a/pkg/ui/v1alpha3/frontend/src/reducers/general.js b/pkg/ui/v1alpha3/frontend/src/reducers/general.js
index d0820359025..84fef88682e 100644
--- a/pkg/ui/v1alpha3/frontend/src/reducers/general.js
+++ b/pkg/ui/v1alpha3/frontend/src/reducers/general.js
@@ -52,7 +52,8 @@ const generalReducer = (state = initialState, action) => {
return {
...state,
deleteDialog: true,
- deleteExperimentName: action.experimentName,
+ deleteExperimentName: action.name,
+ deleteExperimentNamespace: action.namespace,
}
case actions.CLOSE_DELETE_EXPERIMENT_DIALOG:
return {
diff --git a/pkg/ui/v1alpha3/frontend/src/reducers/hpCreate.js b/pkg/ui/v1alpha3/frontend/src/reducers/hpCreate.js
index ad3f8ffe1a0..9631c8c8a44 100644
--- a/pkg/ui/v1alpha3/frontend/src/reducers/hpCreate.js
+++ b/pkg/ui/v1alpha3/frontend/src/reducers/hpCreate.js
@@ -241,6 +241,11 @@ const hpCreateReducer = (state = initialState, action) => {
...state,
trial: action.trial,
}
+ case actions.CHANGE_TRIAL_NAMESPACE_HP:
+ return {
+ ...state,
+ trialNamespace: action.namespace,
+ }
default:
return state;
}
diff --git a/pkg/ui/v1alpha3/frontend/src/sagas/index.js b/pkg/ui/v1alpha3/frontend/src/sagas/index.js
index 203208ccb38..8b87a797213 100644
--- a/pkg/ui/v1alpha3/frontend/src/sagas/index.js
+++ b/pkg/ui/v1alpha3/frontend/src/sagas/index.js
@@ -8,7 +8,7 @@ import * as nasCreateActions from '../actions/nasCreateActions';
import * as generalActions from '../actions/generalActions';
-export const submitYaml = function *() {
+export const submitYaml = function* () {
while (true) {
const action = yield take(generalActions.SUBMIT_YAML_REQUEST);
try {
@@ -24,7 +24,7 @@ export const submitYaml = function *() {
yield put({
type: generalActions.SUBMIT_YAML_FAILURE,
message: result.message,
- })
+ })
}
} catch (err) {
yield put({
@@ -34,7 +34,7 @@ export const submitYaml = function *() {
}
}
-const goSubmitYaml = function *(yaml) {
+const goSubmitYaml = function* (yaml) {
try {
const data = {
yaml
@@ -53,13 +53,14 @@ const goSubmitYaml = function *(yaml) {
}
}
-export const deleteExperiment = function *() {
+export const deleteExperiment = function* () {
while (true) {
const action = yield take(generalActions.DELETE_EXPERIMENT_REQUEST);
try {
const result = yield call(
goDeleteExperiment,
- action.experimentName
+ action.name,
+ action.namespace,
)
if (result.status === 200) {
yield put({
@@ -68,7 +69,7 @@ export const deleteExperiment = function *() {
} else {
yield put({
type: generalActions.DELETE_EXPERIMENT_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -78,11 +79,11 @@ export const deleteExperiment = function *() {
}
}
-const goDeleteExperiment = function *(experimentName) {
+const goDeleteExperiment = function* (name, namespace) {
try {
const result = yield call(
axios.get,
- `/katib/delete_experiment/?experimentName=${experimentName}`,
+ `/katib/delete_experiment/?experimentName=${name}&namespace=${namespace}`,
)
return result
} catch (err) {
@@ -92,7 +93,7 @@ const goDeleteExperiment = function *(experimentName) {
}
}
-export const submitHPJob = function *() {
+export const submitHPJob = function* () {
while (true) {
const action = yield take(hpCreateActions.SUBMIT_HP_JOB_REQUEST);
try {
@@ -108,7 +109,7 @@ export const submitHPJob = function *() {
yield put({
type: hpCreateActions.SUBMIT_HP_JOB_FAILURE,
message: result.message,
- })
+ })
}
} catch (err) {
yield put({
@@ -118,7 +119,7 @@ export const submitHPJob = function *() {
}
}
-const goSubmitHPJob = function *(postData) {
+const goSubmitHPJob = function* (postData) {
try {
const data = {
postData
@@ -137,7 +138,7 @@ const goSubmitHPJob = function *(postData) {
}
}
-export const fetchHPJobs = function *() {
+export const fetchHPJobs = function* () {
while (true) {
const action = yield take(hpMonitorActions.FETCH_HP_JOBS_REQUEST);
try {
@@ -160,7 +161,7 @@ export const fetchHPJobs = function *() {
} else {
yield put({
type: hpMonitorActions.FETCH_HP_JOBS_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -170,7 +171,7 @@ export const fetchHPJobs = function *() {
}
}
-const goFetchHPJobs = function *() {
+const goFetchHPJobs = function* () {
try {
const result = yield call(
axios.get,
@@ -184,13 +185,14 @@ const goFetchHPJobs = function *() {
}
}
-export const fetchHPJobInfo = function *() {
+export const fetchHPJobInfo = function* () {
while (true) {
const action = yield take(hpMonitorActions.FETCH_HP_JOB_INFO_REQUEST);
try {
const result = yield call(
goFetchHPJobInfo,
- action.experimentName
+ action.name,
+ action.namespace
)
if (result.status === 200) {
let data = result.data.split("\n").map((line, i) => line.split(','))
@@ -201,7 +203,7 @@ export const fetchHPJobInfo = function *() {
} else {
yield put({
type: hpMonitorActions.FETCH_HP_JOB_INFO_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -211,11 +213,11 @@ export const fetchHPJobInfo = function *() {
}
}
-const goFetchHPJobInfo = function *(experimentName) {
+const goFetchHPJobInfo = function* (name, namespace) {
try {
const result = yield call(
axios.get,
- `/katib/fetch_hp_job_info/?experimentName=${experimentName}`,
+ `/katib/fetch_hp_job_info/?experimentName=${name}&namespace=${namespace}`,
)
return result
} catch (err) {
@@ -225,7 +227,7 @@ const goFetchHPJobInfo = function *(experimentName) {
}
}
-export const fetchHPJobTrialInfo = function *() {
+export const fetchHPJobTrialInfo = function* () {
while (true) {
const action = yield take(hpMonitorActions.FETCH_HP_JOB_TRIAL_INFO_REQUEST);
try {
@@ -242,7 +244,7 @@ export const fetchHPJobTrialInfo = function *() {
} else {
yield put({
type: hpMonitorActions.FETCH_HP_JOB_TRIAL_INFO_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -252,7 +254,7 @@ export const fetchHPJobTrialInfo = function *() {
}
}
-const gofetchHPJobTrialInfo = function *(trialName) {
+const gofetchHPJobTrialInfo = function* (trialName) {
try {
const result = yield call(
axios.get,
@@ -266,7 +268,7 @@ const gofetchHPJobTrialInfo = function *(trialName) {
}
}
-export const submitNASJob = function *() {
+export const submitNASJob = function* () {
while (true) {
const action = yield take(nasCreateActions.SUBMIT_NAS_JOB_REQUEST);
try {
@@ -282,7 +284,7 @@ export const submitNASJob = function *() {
yield put({
type: nasCreateActions.SUBMIT_NAS_JOB_FAILURE,
message: result.message,
- })
+ })
}
} catch (err) {
yield put({
@@ -292,7 +294,7 @@ export const submitNASJob = function *() {
}
}
-const goSubmitNASJob = function *(postData) {
+const goSubmitNASJob = function* (postData) {
try {
const data = {
postData
@@ -312,7 +314,7 @@ const goSubmitNASJob = function *(postData) {
}
-export const fetchNASJobs = function *() {
+export const fetchNASJobs = function* () {
while (true) {
const action = yield take(nasMonitorActions.FETCH_NAS_JOBS_REQUEST);
try {
@@ -335,7 +337,7 @@ export const fetchNASJobs = function *() {
} else {
yield put({
type: nasMonitorActions.FETCH_NAS_JOBS_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -345,7 +347,7 @@ export const fetchNASJobs = function *() {
}
}
-const goFetchNASJobs = function *() {
+const goFetchNASJobs = function* () {
try {
const result = yield call(
axios.get,
@@ -359,7 +361,7 @@ const goFetchNASJobs = function *() {
}
}
-export const fetchNASJobInfo = function *() {
+export const fetchNASJobInfo = function* () {
while (true) {
const action = yield take(nasMonitorActions.FETCH_NAS_JOB_INFO_REQUEST);
try {
@@ -383,7 +385,7 @@ export const fetchNASJobInfo = function *() {
} else {
yield put({
type: nasMonitorActions.FETCH_NAS_JOB_INFO_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -393,7 +395,7 @@ export const fetchNASJobInfo = function *() {
}
}
-const goFetchNASJobInfo = function *(experimentName) {
+const goFetchNASJobInfo = function* (experimentName) {
try {
const result = yield call(
axios.get,
@@ -408,7 +410,7 @@ const goFetchNASJobInfo = function *(experimentName) {
}
-export const fetchTrialTemplates = function *() {
+export const fetchTrialTemplates = function* () {
while (true) {
const action = yield take(templateActions.FETCH_TRIAL_TEMPLATES_REQUEST);
try {
@@ -432,7 +434,7 @@ export const fetchTrialTemplates = function *() {
} else {
yield put({
type: templateActions.FETCH_TRIAL_TEMPLATES_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -442,7 +444,7 @@ export const fetchTrialTemplates = function *() {
}
}
-const goFetchTrialTemplates = function *(namespace) {
+const goFetchTrialTemplates = function* (namespace) {
try {
const result = yield call(
axios.get,
@@ -456,7 +458,7 @@ const goFetchTrialTemplates = function *(namespace) {
}
}
-export const addTemplate = function *() {
+export const addTemplate = function* () {
while (true) {
const action = yield take(templateActions.ADD_TEMPLATE_REQUEST);
try {
@@ -484,7 +486,7 @@ export const addTemplate = function *() {
} else {
yield put({
type: templateActions.ADD_TEMPLATE_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -494,7 +496,7 @@ export const addTemplate = function *() {
}
}
-const goAddTemplate = function *(name, yaml, kind, action) {
+const goAddTemplate = function* (name, yaml, kind, action) {
try {
const data = {
name, yaml, kind, action
@@ -512,7 +514,7 @@ const goAddTemplate = function *(name, yaml, kind, action) {
}
}
-export const editTemplate = function *() {
+export const editTemplate = function* () {
while (true) {
const action = yield take(templateActions.EDIT_TEMPLATE_REQUEST);
try {
@@ -540,7 +542,7 @@ export const editTemplate = function *() {
} else {
yield put({
type: templateActions.EDIT_TEMPLATE_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -550,7 +552,7 @@ export const editTemplate = function *() {
}
}
-const goEditTemplate = function *(name, yaml, kind, action) {
+const goEditTemplate = function* (name, yaml, kind, action) {
try {
const data = {
name, yaml, kind, action
@@ -568,7 +570,7 @@ const goEditTemplate = function *(name, yaml, kind, action) {
}
}
-export const deleteTemplate = function *() {
+export const deleteTemplate = function* () {
while (true) {
const action = yield take(templateActions.DELETE_TEMPLATE_REQUEST);
try {
@@ -595,7 +597,7 @@ export const deleteTemplate = function *() {
} else {
yield put({
type: templateActions.DELETE_TEMPLATE_FAILURE,
- })
+ })
}
} catch (err) {
yield put({
@@ -605,7 +607,7 @@ export const deleteTemplate = function *() {
}
}
-const goDeleteTemplate = function *(name, kind, action) {
+const goDeleteTemplate = function* (name, kind, action) {
try {
const data = {
name, kind, action
@@ -628,7 +630,7 @@ export default function* rootSaga() {
fork(fetchTrialTemplates),
fork(fetchHPJobs),
fork(fetchNASJobs),
- fork(addTemplate),
+ fork(addTemplate),
fork(editTemplate),
fork(deleteTemplate),
fork(submitYaml),
diff --git a/pkg/ui/v1alpha3/nas.go b/pkg/ui/v1alpha3/nas.go
new file mode 100644
index 00000000000..02bb1c7fde1
--- /dev/null
+++ b/pkg/ui/v1alpha3/nas.go
@@ -0,0 +1,106 @@
+package v1alpha3
+
+import (
+ "context"
+ "encoding/json"
+ "log"
+ "net/http"
+ "strconv"
+
+ trialsv1alpha3 "github.com/kubeflow/katib/pkg/apis/controller/trials/v1alpha3"
+ api_pb_v1alpha3 "github.com/kubeflow/katib/pkg/apis/manager/v1alpha3"
+ "github.com/kubeflow/katib/pkg/controller.v1alpha3/consts"
+)
+
+func (k *KatibUIHandler) FetchNASJobs(w http.ResponseWriter, r *http.Request) {
+ //enableCors(&w)
+ jobs, err := k.getExperimentList(consts.DefaultKatibNamespace, JobTypeNAS)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ response, err := json.Marshal(jobs)
+ if err != nil {
+ log.Printf("Marshal NAS jobs failed: %v", err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ w.Write(response)
+}
+
+func (k *KatibUIHandler) FetchNASJobInfo(w http.ResponseWriter, r *http.Request) {
+ //enableCors(&w)
+ experimentName := r.URL.Query()["experimentName"][0]
+
+ responseRaw := make([]NNView, 0)
+ var architecture string
+ var decoder string
+
+ conn, c := k.connectManager()
+
+ defer conn.Close()
+
+ trials, err := k.katibClient.GetTrialList(experimentName)
+ if err != nil {
+ log.Printf("GetTrialList from NAS job failed: %v", err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ log.Printf("Got Trial List")
+
+ for i, t := range trials.Items {
+ succeeded := false
+ for _, condition := range t.Status.Conditions {
+ if condition.Type == trialsv1alpha3.TrialSucceeded {
+ succeeded = true
+ }
+ }
+ if succeeded {
+ obsLogResp, err := c.GetObservationLog(
+ context.Background(),
+ &api_pb_v1alpha3.GetObservationLogRequest{
+ TrialName: t.Name,
+ StartTime: "",
+ EndTime: "",
+ },
+ )
+ if err != nil {
+ log.Printf("GetObservationLog from NAS job failed: %v", err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ metricsName := make([]string, 0)
+ metricsValue := make([]string, 0)
+ for _, m := range obsLogResp.ObservationLog.MetricLogs {
+ metricsName = append(metricsName, m.Metric.Name)
+ metricsValue = append(metricsValue, m.Metric.Value)
+
+ }
+ for _, trialParam := range t.Spec.ParameterAssignments {
+ if trialParam.Name == "architecture" {
+ architecture = trialParam.Value
+ }
+ if trialParam.Name == "nn_config" {
+ decoder = trialParam.Value
+ }
+ }
+ responseRaw = append(responseRaw, NNView{
+ Name: "Generation " + strconv.Itoa(i),
+ TrialName: t.Name,
+ Architecture: generateNNImage(architecture, decoder),
+ MetricsName: metricsName,
+ MetricsValue: metricsValue,
+ })
+ }
+ }
+ log.Printf("Logs parsed, result: %v", responseRaw)
+
+ response, err := json.Marshal(responseRaw)
+ if err != nil {
+ log.Printf("Marshal result in NAS job failed: %v", err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ w.Write(response)
+}
diff --git a/pkg/ui/v1alpha3/types.go b/pkg/ui/v1alpha3/types.go
index fb1a484da51..7c0784092d6 100644
--- a/pkg/ui/v1alpha3/types.go
+++ b/pkg/ui/v1alpha3/types.go
@@ -1,6 +1,8 @@
-package ui
+package v1alpha3
-import "github.com/kubeflow/katib/pkg/util/v1alpha3/katibclient"
+import (
+ "github.com/kubeflow/katib/pkg/util/v1alpha3/katibclient"
+)
const maxMsgSize = 1<<31 - 1
@@ -29,8 +31,9 @@ type Option struct {
}
type JobView struct {
- Name string
- Status string
+ Name string
+ Status string
+ Namespace string
}
type TemplateView struct {
@@ -54,3 +57,10 @@ type NNView struct {
MetricsName []string
MetricsValue []string
}
+
+type JobType string
+
+const (
+ JobTypeHP = "HP"
+ JobTypeNAS = "NAS"
+)
diff --git a/pkg/ui/v1alpha3/util.go b/pkg/ui/v1alpha3/util.go
index f35c30502ac..289d6b04f10 100644
--- a/pkg/ui/v1alpha3/util.go
+++ b/pkg/ui/v1alpha3/util.go
@@ -1,8 +1,9 @@
-package ui
+package v1alpha3
import (
"encoding/json"
"errors"
+ "log"
"net/http"
"strconv"
"strings"
@@ -10,6 +11,32 @@ import (
gographviz "github.com/awalterschulze/gographviz"
)
+func (k *KatibUIHandler) getExperimentList(namespace string, typ JobType) ([]JobView, error) {
+ jobs := make([]JobView, 0)
+
+ el, err := k.katibClient.GetExperimentList(namespace)
+ if err != nil {
+ log.Printf("GetExperimentList failed: %v", err)
+ return nil, err
+ }
+ for _, experiment := range el.Items {
+ if (typ == JobTypeNAS && experiment.Spec.NasConfig != nil) ||
+ (typ == JobTypeHP && experiment.Spec.NasConfig == nil) {
+ experimentLastCondition, err := experiment.GetLastConditionType()
+ if err != nil {
+ log.Printf("GetLastConditionType failed: %v", err)
+ return nil, err
+ }
+ jobs = append(jobs, JobView{
+ Name: experiment.Name,
+ Namespace: experiment.Namespace,
+ Status: string(experimentLastCondition),
+ })
+ }
+ }
+ return jobs, nil
+}
+
func enableCors(w *http.ResponseWriter) {
(*w).Header().Set("Content-Type", "text/html; charset=utf-8")
(*w).Header().Set("Access-Control-Allow-Origin", "*")