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

Add users list to vm details page #5698

Merged
merged 1 commit into from Jun 10, 2020

Conversation

yaacov
Copy link
Member

@yaacov yaacov commented Jun 9, 2020

Add users list to vm details

Design:
http://openshift.github.io/openshift-origin-design/designs/virtualization/4.x/expose-guest-data/expose%20guest%20data.html#details-tab

Screenshot:
two users is logged in
two-users-loggedin

guest agent is not installed
no-guest-agent

no logged in users
screenshot-localhost_9000-2020 06 09-21_09_18

vm is not running
screenshot-localhost_9000-2020 06 09-21_05_29

load error:
screenshot-localhost_9000-2020 06 09-23_35_09

@openshift-ci-robot openshift-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 9, 2020
@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

@pcbailey please reveiw

@openshift-ci-robot openshift-ci-robot added component/kubevirt Related to kubevirt-plugin approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Jun 9, 2020
@yaacov yaacov force-pushed the add-user-list branch 2 times, most recently from 1f07213 to d625935 Compare June 9, 2020 12:58
@yaacov yaacov changed the title [WIP] Add users list to vm details page Add users list to vm details page Jun 9, 2020
@openshift-ci-robot openshift-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 9, 2020
@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

@suomiy @pcbailey @glekner @irosenzw please review

props: { className: tableColumnClasses[1] },
},
{
title: 'Log in time',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use "Login time" instead of "Log in time". There's a slight difference between the two. "Log in" is an instruction to someone to log in to the system, with "log" being used as a verb. A "login" is a noun and refers to either the credentials used to log in to a system or a specific instance where a user has logged in.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm.. thanks !
did look a little off to me didn't know why :-)


const UsersTableRow = ({ obj, index, key, style }) => {
return (
<TableRow id={obj?.metadata.uid} index={index} trKey={key} style={style}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What isobj? I assume it's user information. I would recommend using a more descriptive name unless there's a reason to leave it generic. Could we use selectors to access the properties of obj?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice +1, fixed

{obj?.metadata?.domain}
</TableData>
<TableData className={tableColumnClasses[2]}>
<Timestamp timestamp={new Date(obj?.metadata?.loginTime).toUTCString()} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much cleaner than the date formatting code you were working with before. =)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes :-)

return (
<StatusItem
Icon={BlueInfoCircleIcon}
message="This VM does not have guest agent installed. Some metrics and management features will not be available."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add this message text as a constant in one of the strings files so we can use it wherever it's needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 80 to 107
const url = `apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`;

const usersResult = urlResults.getIn([url, 'data']);
const usersResultError = urlResults.getIn([url, 'loadError']);

const data =
usersResult &&
usersResult?.userList &&
usersResult?.userList.map((u) => ({
metadata: {
name: u?.userName,
domain: u?.domain,
loginTime: u?.loginTime && u.loginTime * 1000,
},
}));

React.useEffect(() => {
watchURL(url);
return () => {
stopWatchURL(url);
};
}, [watchURL, stopWatchURL, url]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we're going to put this code in a centralized location? I can add it to my existing PR if you want, and maybe create a wrapper class to make it easier to work with. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yaacov @pcbailey
Are you sure we should be using withDashboardResources HOC for list which is not inside the dashboard?

We are going to reuse this url call in multiple places?

Having a hook for this would be nice. It would be also nicer if we could remove the HOC altogether and have all the logic in the hook.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@suomiy @yaacov We don't plan on using the dashboard code in the final implementation. We're going to write our own and will likely favor using a hook over a HOC. We're just using the dashboard code as a starting point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


const name = getName(vmi);
const namespace = getNamespace(vmi);
const url = `apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make a function out of this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 80 to 107
const url = `apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`;

const usersResult = urlResults.getIn([url, 'data']);
const usersResultError = urlResults.getIn([url, 'loadError']);

const data =
usersResult &&
usersResult?.userList &&
usersResult?.userList.map((u) => ({
metadata: {
name: u?.userName,
domain: u?.domain,
loginTime: u?.loginTime && u.loginTime * 1000,
},
}));

React.useEffect(() => {
watchURL(url);
return () => {
stopWatchURL(url);
};
}, [watchURL, stopWatchURL, url]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yaacov @pcbailey
Are you sure we should be using withDashboardResources HOC for list which is not inside the dashboard?

We are going to reuse this url call in multiple places?

Having a hook for this would be nice. It would be also nicer if we could remove the HOC altogether and have all the logic in the hook.

usersResult &&
usersResult?.userList &&
usersResult?.userList.map((u) => ({
metadata: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we do this for name sorting, but still it is a bit weird to wrap everything in metadata. I wonder if we can do something about it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahhh, forgot to do the sorting ... addning sort ( I knew the metadata has a reason :-) )

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the missing sort


const tableColumnClasses = [
classNames('col-lg-3', 'col-md-3', 'col-sm-4', 'col-xs-6'),
classNames('col-lg-3', 'col-md-3', 'col-sm-4', 'hidden-xs'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the domain? Is it a good decision to hide it for smaller devices?

Shouldn't we switch the priority and show the Login time instead of Elapsed login time on smaller devices? Especially, because there is timezone in Login time

Copy link
Member Author

@yaacov yaacov Jun 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the domain?

domain is the ip address user logged in from, if we need to choose logged in time and domain, I'll choose logged in time

Shouldn't we switch the priority and show the Login time instead of Elapsed login time on smaller devices? Especially, because there is timezone in Login time

make sense to me too, switching

p.s.
@matthewcarleton in the designs do we have a way to specify how things look on small screens ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

domain is the ip address user logged in from, if we need to choose logged in time and domain, I'll choose logged in time

I see, I vote for having user | domain | login time visible every time

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok :-) fixing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the domain?

domain is the ip address user logged in from, if we need to choose logged in time and domain, I'll choose logged in time

Shouldn't we switch the priority and show the Login time instead of Elapsed login time on smaller devices? Especially, because there is timezone in Login time

make sense to me too, switching

p.s.
@matthewcarleton in the designs do we have a way to specify how things look on small screens ?

If we are using a PF4 component it should be good for mobile right? Is there anything unique about this that doesn't just use a default PF table?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are using a PF4 component it should be good for mobile right? Is there anything unique about this that doesn't just use a default PF table?

@matthewcarleton
yes, the question here is witch columns should magically disappear on small displays.
The discussion above is: should we show 3 or only 2 columns on extra small display.

for example we decided here to show 3 columns ( removed the elapsed time ):
screenshot-localhost_9000-2020 06 09-21_21_40

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I didn't get this before it merged but we should be using a modifier class to get the responsive state.
If you use pf-m-grid-md you won't need to remove that column for smaller screens b/c it will stack.

@yaacov yaacov force-pushed the add-user-list branch 4 times, most recently from f23851a to 69bd9d1 Compare June 9, 2020 14:35
@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

@pcbailey @suomiy I addressed all the issues except the replacement for the withDashboardResources can you re-review ?

@matthewcarleton
Copy link
Contributor

Add users list to vm details

Design:
http://openshift.github.io/openshift-origin-design/designs/virtualization/4.x/expose-guest-data/expose%20guest%20data.html#details-tab

Screenshot:
two users is logged in
two-users-loggedin

What's the reason for the Login time being blue?

guest agent is not installed
no-guest-agent
This text could say
This virtual machine does not have the guest agent installed, therefor, user data can not be reported.

no logged in users
no-logged-in-user

The text for "No Logged in Users" should probably look the same as the empty state for the services empty state above (centered, and darker)

vm is not running
vm-not-running

Same here for that empty state

@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

What's the reason for the Login time being blue?

Patternfly table makes the sorted column blue, see:
https://www.patternfly.org/v4/documentation/react/components/table#sortable

@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

/test e2e-gcp-console

@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

The text for "No Logged in Users" should probably look the same as the empty state for the services empty state above (centered, and darker)

fixed :-)

@yaacov
Copy link
Member Author

yaacov commented Jun 9, 2020

@suomiy @pcbailey removed the 'withDashboardResources' 🎉 , please re-review

@@ -0,0 +1,152 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { watchURL, stopWatchURL } from '@console/internal/actions/dashboards';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont use dashboards stuff outside of dashboards. It would be good to create a new hook for polling some url. You can take a look at https://github.com/openshift/console/blob/master/frontend/public/components/graphs/prometheus-poll-hook.ts - create something generic and reuse it also in prometheus-poll-hook

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks ! using pool hook now

import { VMIKind } from '../../types';

const guestAgentURL = (name: string, namespace: string) =>
`apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's already logic for creating subresources url such as https://github.com/openshift/console/blob/master/frontend/packages/kubevirt-plugin/src/selectors/vmi/combined.ts#L60

you should try to reuse that

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fixed now :-)

}));

// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a coditional usage of hook. It needs to be moved on top before all if/returns

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@yaacov
Copy link
Member Author

yaacov commented Jun 10, 2020

/test e2e-gcp-console

@openshift-ci-robot openshift-ci-robot added the component/core Related to console core functionality label Jun 10, 2020
@openshift-ci-robot openshift-ci-robot removed the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 10, 2020
const DEFAULT_SAMPLES = 60;
const DEFAULT_TIMESPAN = 60 * 60 * 1000; // 1 hour

export const usePrometheusPoll = ({
delay = DEFAULT_DELAY,
delay = URL_POLL_DEFAULT_DELAY,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to define the default value as url-poll hook does that.

Suggested change
delay = URL_POLL_DEFAULT_DELAY,
delay,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


export const URL_POLL_DEFAULT_DELAY = 15000; // 15 seconds

export const useURLPoll = (
Copy link
Contributor

@rawagner rawagner Jun 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could improve the types with some generics. Like defining the return value to not be any

Suggested change
export const useURLPoll = (
export const useURLPoll = <R>(
url: string,
delay = URL_POLL_DEFAULT_DELAY,
...dependencies: any[]
): URLPoll<R> => {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice !

return { response, error, loading };
};

export type URLPoll = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export type URLPoll = {
export type URLPoll<R> = [ R, any, boolean ];


usePoll(tick, delay, ...dependencies);

return { response, error, loading };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to return an array to align with other hooks

Suggested change
return { response, error, loading };
return [ response, error, loading ];

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@@ -0,0 +1,46 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useCallback, useState } from 'react';
import { usePoll, useSafeFetch } from '.';
Copy link
Contributor

@rawagner rawagner Jun 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please dont import from index file, it causes circular deps

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -59,3 +59,4 @@ export { default } from './operator-backed-owner-references';
export * from './field-level-help';
export * from './details-item';
export * from './types';
export * from './use-url-hook';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets not add this hook to index file. We want to remove all indexes as they cause issues due to circular deps

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

}, [url]);

usePoll(tick, delay, endTime, query, timespan);
const { response, error, loading } = useURLPoll(url, delay, endTime, query, timespan);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you use array format and generics for useURLPoll use can do

Suggested change
const { response, error, loading } = useURLPoll(url, delay, endTime, query, timespan);
return useURLPoll<PrometheusResponse>(url, delay, endTime, query, timespan);

@@ -0,0 +1,46 @@
/* eslint-disable react-hooks/exhaustive-deps */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to align with other hooks we should call this file url-poll-hook

...dependencies: any[]
): URLPoll => {
const [error, setError] = useState();
const [response, setResponse] = useState();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const [response, setResponse] = useState();
const [response, setResponse] = useState<R>();

@rawagner
Copy link
Contributor

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Jun 10, 2020
@openshift-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: rawagner, yaacov

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 10, 2020
@openshift-merge-robot openshift-merge-robot merged commit 2aae8b3 into openshift:master Jun 10, 2020
@spadgett spadgett added this to the v4.6 milestone Jun 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. component/core Related to console core functionality component/kubevirt Related to kubevirt-plugin lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants