Skip to content

Commit

Permalink
feat: Support namespace in NAS UI (#839)
Browse files Browse the repository at this point in the history
* feat: Support namespace in monitor

Signed-off-by: Ce Gao <gaoce@caicloud.io>

* feat: Support namesapce in create tag

Signed-off-by: Ce Gao <gaoce@caicloud.io>
  • Loading branch information
gaocegege authored and k8s-ci-robot committed Sep 30, 2019
1 parent cb6de0d commit e0659b4
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 233 deletions.
2 changes: 1 addition & 1 deletion cmd/ui/v1alpha3/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func main() {
http.Handle("/katib/", http.StripPrefix("/katib/", frontend))

http.HandleFunc("/katib/fetch_hp_jobs/", kuh.FetchAllHPJobs)
http.HandleFunc("/katib/fetch_nas_jobs/", kuh.FetchNASJobs)
http.HandleFunc("/katib/fetch_nas_jobs/", kuh.FetchAllNASJobs)
http.HandleFunc("/katib/submit_yaml/", kuh.SubmitYamlJob)
http.HandleFunc("/katib/submit_hp_job/", kuh.SubmitParamsJob)
http.HandleFunc("/katib/submit_nas_job/", kuh.SubmitParamsJob)
Expand Down
161 changes: 0 additions & 161 deletions pkg/ui/v1alpha3/backend.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package v1alpha3

import (
"context"
"encoding/json"
"log"
"net/http"
"strings"
"time"

"github.com/ghodss/yaml"
"google.golang.org/grpc"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

experimentv1alpha3 "github.com/kubeflow/katib/pkg/apis/controller/experiments/v1alpha3"
trialsv1alpha3 "github.com/kubeflow/katib/pkg/apis/controller/trials/v1alpha3"
api_pb_v1alpha3 "github.com/kubeflow/katib/pkg/apis/manager/v1alpha3"
common_v1alpha3 "github.com/kubeflow/katib/pkg/common/v1alpha3"
"github.com/kubeflow/katib/pkg/controller.v1alpha3/consts"
Expand Down Expand Up @@ -42,41 +38,6 @@ func (k *KatibUIHandler) connectManager() (*grpc.ClientConn, api_pb_v1alpha3.Man
return conn, c
}

func (k *KatibUIHandler) FetchHPJobs(w http.ResponseWriter, r *http.Request) {
//enableCors(&w)
jobs, err := k.getExperimentList(consts.DefaultKatibNamespace, JobTypeHP)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

response, err := json.Marshal(jobs)
if err != nil {
log.Printf("Marshal HP jobs failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(response)

}

// 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 {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
response, err := json.Marshal(jobs)
if err != nil {
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) {
//enableCors(&w)
var data map[string]interface{}
Expand Down Expand Up @@ -155,128 +116,6 @@ 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, namespace)
if err != nil {
log.Printf("GetExperiment from HP job failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Printf("Got Experiment")
metricsList := map[string]int{}
metricsName := experiment.Spec.Objective.ObjectiveMetricName
resultText += "," + metricsName
metricsList[metricsName] = 0
for i, m := range experiment.Spec.Objective.AdditionalMetricNames {
resultText += "," + m
metricsList[m] = i + 1
}
log.Printf("Got metrics names")
paramList := map[string]int{}
for i, p := range experiment.Spec.Parameters {
resultText += "," + p.Name
paramList[p.Name] = i + len(metricsList)
}
log.Printf("Got Parameters names")

trialList, err := k.katibClient.GetTrialList(experimentName)
if err != nil {
log.Printf("GetTrialList from HP job failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Printf("Got Trial List")

for _, t := range trialList.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 HP job failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

trialResText := make([]string, len(metricsList)+len(paramList))
for _, m := range obsLogResp.ObservationLog.MetricLogs {
trialResText[metricsList[m.Metric.Name]] = m.Metric.Value

}
for _, trialParam := range t.Spec.ParameterAssignments {
trialResText[paramList[trialParam.Name]] = trialParam.Value
}
resultText += "\n" + t.Name + "," + strings.Join(trialResText, ",")
}
}
log.Printf("Logs parsed, results:\n %v", resultText)
response, err := json.Marshal(resultText)
if err != nil {
log.Printf("Marshal result text for HP job failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(response)
}

func (k *KatibUIHandler) FetchHPJobTrialInfo(w http.ResponseWriter, r *http.Request) {
//enableCors(&w)
trialName := r.URL.Query()["trialName"][0]
conn, c := k.connectManager()
defer conn.Close()

resultText := "metricName,time,value\n"
obsLogResp, err := c.GetObservationLog(
context.Background(),
&api_pb_v1alpha3.GetObservationLogRequest{
TrialName: trialName,
StartTime: "",
EndTime: "",
},
)
if err != nil {
log.Printf("GetObservationLog failed: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
prevTime := ""
for _, m := range obsLogResp.ObservationLog.MetricLogs {
parsedTime, _ := time.Parse(time.RFC3339Nano, m.TimeStamp)
formatTime := parsedTime.Format("2006-01-02T15:4:5")
if formatTime != prevTime {
resultText += m.Metric.Name + "," + formatTime + "," + m.Metric.Value + "\n"
prevTime = formatTime
}
}

response, err := json.Marshal(resultText)
if err != nil {
log.Printf("Marshal result text in Trial info 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)
Expand Down
7 changes: 7 additions & 0 deletions pkg/ui/v1alpha3/frontend/src/actions/nasCreateActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ export const changeTrial = (trial) => ({
trial,
})

export const CHANGE_TRIAL_NAMESPACE_NAS = "CHANGE_TRIAL_NAMESPACE_HP";

export const changeTrialNamespace = (namespace) => ({
type: CHANGE_TRIAL_NAMESPACE_NAS,
namespace,
})

export const SUBMIT_NAS_JOB_REQUEST = "SUBMIT_NAS_JOB_REQUEST";
export const SUBMIT_NAS_JOB_SUCCESS = "SUBMIT_NAS_JOB_SUCCESS";
export const SUBMIT_NAS_JOB_FAILURE = "SUBMIT_NAS_JOB_FAILURE";
Expand Down
5 changes: 3 additions & 2 deletions pkg/ui/v1alpha3/frontend/src/actions/nasMonitorActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export const FETCH_NAS_JOB_INFO_REQUEST = "FETCH_NAS_JOB_INFO_REQUEST";
export const FETCH_NAS_JOB_INFO_SUCCESS = "FETCH_NAS_JOB_INFO_SUCCESS";
export const FETCH_NAS_JOB_INFO_FAILURE = "FETCH_NAS_JOB_INFO_FAILURE";

export const fetchNASJobInfo = (experimentName) => ({
export const fetchNASJobInfo = (experimentName, namespace) => ({
type: FETCH_NAS_JOB_INFO_REQUEST,
experimentName
experimentName,
namespace
})
2 changes: 1 addition & 1 deletion pkg/ui/v1alpha3/frontend/src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const App = (props) => {
<Route path="/katib/hp_monitor/:namespace/:name" component={HPJobInfo} />
<Route path="/katib/nas" component={NAS} />
<Route exact path="/katib/nas_monitor" component={NASJobMonitor} />
<Route path="/katib/nas_monitor/:name" component={NASJobInfo} />
<Route path="/katib/nas_monitor/:namespace/:name" component={NASJobInfo} />
<Route path="/katib/trial" component={Trial} />
<Snack />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const NASParameters = (props) => {
goTemplate: {
templateSpec: {
configMapName: "trial-template",
configMapNamespace: data.metadata.namespace,
configMapNamespace: props.trialNamespace,
templatePath: props.trial,
}
}
Expand Down Expand Up @@ -191,7 +191,8 @@ const mapStateToProps = (state) => ({
inputSize: state[module].inputSize,
outputSize: state[module].outputSize,
operations: state[module].operations,
trial: state[module].trial
trial: state[module].trial,
trialNamespace: state[module].trialNamespace,
})

//TODO: Added validation and remove it
Expand Down
84 changes: 54 additions & 30 deletions pkg/ui/v1alpha3/frontend/src/components/NAS/Create/Params/Trial.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import TextField from '@material-ui/core/TextField';

import { connect } from 'react-redux';
import { changeTrial } from '../../../../actions/nasCreateActions';
import { changeTrial, changeTrialNamespace } from '../../../../actions/nasCreateActions';
import { fetchTrialTemplates } from '../../../../actions/templateActions';

const module = "nasCreate";
Expand Down Expand Up @@ -41,8 +42,9 @@ const styles = theme => ({

class TrialSpecParam extends React.Component {

componentDidMount() {
this.props.fetchTrialTemplates();
onTrialNamespaceChange = (event) => {
this.props.fetchTrialTemplates(event.target.value);
this.props.changeTrialNamespace(event.target.value);
}

onTrialChange = (event) => {
Expand All @@ -54,38 +56,59 @@ class TrialSpecParam extends React.Component {

const { classes } = this.props
return (
<div className={classes.parameter}>
<Grid container alignItems={"center"}>
<Grid item xs={12} sm={3}>
<Typography variant={"subheading"}>
<Tooltip title={"Trial spec template"}>
<HelpOutlineIcon className={classes.help} color={"primary"}/>
</Tooltip>
{"TrialSpec"}
</Typography>
<div>
<div className={classes.parameter}>
<Grid container alignItems={"center"}>
<Grid item xs={12} sm={3}>
<Typography variant={"subheading"}>
<Tooltip title={"Trial namespace"}>
<HelpOutlineIcon className={classes.help} color={"primary"} />
</Tooltip>
{"Namespace"}
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<TextField
className={"Trial Namespace"}
value={this.props.trialNamespace}
onChange={this.onTrialNamespaceChange}
/>
</Grid>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel>
Trial Spec
</InputLabel>
<Select
value={this.props.trial}
onChange={this.onTrialChange}
input={
<OutlinedInput name={"TrialSpec"} labelWidth={100}/>
}
className={classes.select}
</div>
<div className={classes.parameter}>
<Grid container alignItems={"center"}>
<Grid item xs={12} sm={3}>
<Typography variant={"subheading"}>
<Tooltip title={"Trial spec template"}>
<HelpOutlineIcon className={classes.help} color={"primary"} />
</Tooltip>
{"TrialSpec"}
</Typography>
</Grid>
<Grid item xs={12} sm={8}>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel>
Trial Spec
</InputLabel>
<Select
value={this.props.trial}
onChange={this.onTrialChange}
input={
<OutlinedInput name={"TrialSpec"} labelWidth={100} />
}
className={classes.select}
>
{names.map((spec, i) => {
return (
<MenuItem value={spec} key={i}>{spec}</MenuItem>
)
<MenuItem value={spec} key={i}>{spec}</MenuItem>
)
})}
</Select>
</FormControl>
</Select>
</FormControl>
</Grid>
</Grid>
</Grid>
</div>
</div>
)
}
Expand All @@ -96,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));
Loading

0 comments on commit e0659b4

Please sign in to comment.