Skip to content

Create/Edit page for Webhook secrets #94

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

Merged
merged 1 commit into from
Jun 20, 2018

Conversation

jhadvig
Copy link
Member

@jhadvig jhadvig commented Jun 5, 2018

Added button with Create New dropdown button, which (for now, rest will be added in a follow up) contains:

  • Create Webhook Secret
  • Create via YAML

1

When creating the secret Im adding all the values to the stringData which will take care of encoding the data.

2

I've also added following actions for individual secrets:

  • Modify Labels
  • Modify Annotations
  • Duplicate Secret
  • Edit Secret
  • Delete Secret

3

PTAL

@openshift-ci-robot openshift-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 5, 2018
@@ -68,6 +68,7 @@
"plotly.js": "1.28.x",
"prop-types": "15.6.x",
"react": "16.x",
"react-ace": "6.1.x",
Copy link
Member

Choose a reason for hiding this comment

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

We're already using Ace editor elsewhere (edit YAML). I think we should be able to use Ace here without the new dependency. Can you check?

https://github.com/openshift/console/blob/master/frontend/public/components/edit-yaml.jsx

Copy link
Member

Choose a reason for hiding this comment

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

Sorry I see you comment on this in the description. I think we should discuss further. How large is the library?

Copy link
Member Author

Choose a reason for hiding this comment

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

from what I see in the node_modules it's 2MB. Just for comparision the brace has 8.5MB

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't look at node_modules size. Use yarn run analyze to see the size of the built js.

Copy link
Contributor

@kans kans Jun 6, 2018

Choose a reason for hiding this comment

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

react-ace is a thin wrapper around brace:

https://github.com/securingsincity/react-ace/blob/master/package.json#L63:

  "dependencies": {
    "brace": "^0.11.0",
   ...
},

https://github.com/securingsincity/react-ace/blob/master/src/ace.js#L1:

import ace from 'brace'

react-ace itself is 46.47 KB. Previously we were async loading brace only when needed. Since secret.jsx now imports brace (747KB), our main bundle of vendored deps has increased in size by ~40%.

Are there any interactions here that aren't 90% copy/paste - ie, why do we need a text editor at all? If you do need one, you should use AsyncComponent to load it only when needed since the vast majority of users will not create a secret.

@spadgett
Copy link
Member

spadgett commented Jun 5, 2018

cc @tlwu2013

@robszumski
Copy link
Contributor

Throwing out this multi-create button pattern that we have for OLM:

image

What does @openshift/team-ux-review think of offloading the selection type to this button, which will reduce one of the fields on the screen, plus give you an option to jump to a raw YAML editor. Using a dropdown to switch this will alter the page a ton, plus you have no way to get back.

Create Source Secret...
Create Key/Value Secret...
Create Image Secret...
Create Webhook Secret...
Create via YAML...

Also, I think we need some microcopy work here and none of those phrases mean anything to me:

  • "source" and "image" are very generic and don't match a Kubernetes-ism that I may be looking for
  • I renamed "generic" -> "key/value" above
  • Should "Image" be "ImagePullSecret" (direct) or "Pull Secret" (friendlier)

@kans
Copy link
Contributor

kans commented Jun 6, 2018

Do you mean Opaque instead of Generic? If so, lets use the k8s term.

@spadgett
Copy link
Member

spadgett commented Jun 7, 2018

Not necessarily against using Opaque, but kubectl create secret does call it "generic".

@spadgett
Copy link
Member

spadgett commented Jun 7, 2018

@jhadvig I'd suggest doing these one at a time in separate PRs, maybe starting with opaque secrets. I think we'll be able to get these reviewed and merged quicker that way.

I don't know if the name/value editor will work as-is for generic secrets since they often have multiline values (e.g. certificates and keys).

It would be good to structure this in such a way that we can use the same components for editing secrets, too.

@cshinn
Copy link

cshinn commented Jun 8, 2018

I think @robszumski's idea makes sense. Especially if that selection will drastically change the form underneath. As for terminology, sticking with the K8s standards is probably a good idea

@openshift-bot openshift-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 13, 2018
@openshift-ci-robot openshift-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 13, 2018
@openshift-bot openshift-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 13, 2018
@jhadvig
Copy link
Member Author

jhadvig commented Jun 13, 2018

@spadgett I've update the PR based on the comments from @robszumski
I've replaced the Create Secret button with Create New dropdown button, which (for now, rest will be added in a follow up) contains:

  • Create Webhook Secret
  • Create via YAML

1

When creating the secret Im adding all the values to the stringData which will take care of encoding the data.

2

I've also added following actions for individual secrets:

  • Modify Labels
  • Modify Annotations
  • Duplicate Secret
  • Edit Secret
  • Delete Secret

3

PTAL

@jhadvig jhadvig force-pushed the secret-form branch 3 times, most recently from e0f29ab to 599edb8 Compare June 13, 2018 18:07
@jhadvig jhadvig changed the title [WIP] Create secret page Create secret page Jun 13, 2018
@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 13, 2018
@cshinn
Copy link

cshinn commented Jun 13, 2018

@jhadvig the dropdown panel on the "Create New" button looks a bit misaligned. Looks great other than that

@beanh66
Copy link

beanh66 commented Jun 13, 2018

@jhadvig Thanks this looks good, I just have a few comments:

  • Can we fix the alignment as Chris mentioned?
  • The dropdown can just say "Create" with the caret
  • The options can then be "Secret from YAML" and "Webhook Secret"
  • Options should be alphabetical
  • On the webhook secret form, the padding on the right should match the padding on the left if possible and the action button should be "Create" instead of "Create Secret"

Copy link
Contributor

@alecmerdler alecmerdler left a comment

Choose a reason for hiding this comment

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

We don't need to add complexity to list-page.jsx when the use case is already handled. Also, you should update the description to accurately reflect the state of the PR.

case 'kubernetes.io/dockerconfigjson':
case 'kubernetes.io/dockercfg':
determinedType = 'image';
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

Just return after each case.

case 'source':
case 'image':
case 'generic':
case 'webhook':
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these all supposed to evaluate to WebHookSecretSubform?

Copy link
Member Author

Choose a reason for hiding this comment

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

No.. those are just subform options that console will eventually exist

Copy link
Contributor

Choose a reason for hiding this comment

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

Right now the case statements above will fall through to the 'webhook' option. I would suggest YAGNI here and remove the switch block altogether.

Copy link
Member Author

Choose a reason for hiding this comment

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

True, but the switch will be there once we add all the subforms options. Just wanted to have all the options on mind. But don't have any strong preferences regarding changing it to if statement :)

Copy link
Member

Choose a reason for hiding this comment

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

I'd rather leave out things we don't support yet in this PR.


const BindingLoadingWrapper = props => {
const fixed = {};
_.each(props.fixedKeys, k => fixed[k] = _.get(props.obj.data, k));
Copy link
Contributor

Choose a reason for hiding this comment

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

const fixed = _.reduce(props.fixedKeys, (acc, k) => ({...acc, k: _.get(props.obj.data, k)}), {});

@@ -246,7 +246,19 @@ export const ListPage = props => {
href = namespaced ? `/k8s/ns/${namespace || 'default'}/${ref}/new` : `/k8s/cluster/${ref}/new`;
} catch (unused) { /**/ }
}
const createProps = createHandler ? {onClick: createHandler} : {to: href};
let createProps;
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't necessary, it is already handled in the FireMan_ component.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure how the FireMan_ will evaluate the truly the Dropdown component, since the ListPage component sets createProps either with onClick or to keys, there is no items key set, so there is no way Dropdown will be rendered. Or maybe I'm missing something

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

@jhadvig jhadvig Jun 14, 2018

Choose a reason for hiding this comment

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

But the implementation counts with setting the items which is missing clearly in the ListPage component, since only onClick and to keys are set and therefor there is no way to create a Dropdown button. From what I can tell, those two implementations are used for different use-cases

Copy link
Contributor

Choose a reason for hiding this comment

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

I see what you mean. Try this:

  1. Allow passing createProps as a prop to ListPage
  2. Change this line to:
const createProps = createProps || (createHandler ? {onClick: createHandler} : {to: href});
  1. Change SecretsPage to this:
const SecretsPage = props => {
  const createItems = {
    // source: 'Create Source Secret',
    // image: 'Create Image Pull Secret',
    // generic: 'Create Key/Value Secret',
    webhook: 'Webhook Secret',
    yaml: 'Secret from YAML',
  };

  const createProps = {
    items: createItems,
    createLink: (type) => `/k8s/ns/${props.obj.metadata.namespace}/secrets/${type === 'yaml' ? 'new' : type}`
  };

  return <ListPage ListComponent={SecretsList} canCreate={true} rowFilters={filters} createButtonText="Create" createProps={createProps} {...props} />;
};

I tried this locally and it works.

@jhadvig jhadvig changed the title Create secret page Create/Edit page for Webhook secrets Jun 14, 2018
@jhadvig
Copy link
Member Author

jhadvig commented Jun 14, 2018

@beanh66

Options should be alphabetical

I understand the point but thought that options that will render an actual form should be first and the YAML editor should be the last one and by that somehow logically group them.
Thoughts ?

On the webhook secret form, the padding on the right should match the padding on the left if possible

Sorry for the misleading screen, not sure why but when I took it it chopped off some pixeles from the left padding. The padding is the same on both sides - 30px
screenshot at 2018-06-14 11-24-28

Regarding the issue @cshinn mentioned in his comment, this is an issue in the Dropdown component (it's also visible in #94 (comment)), which would require rework the component itself, so I would rather do it as a followup and open an issue for that one, if you don't mind.

@beanh66
Copy link

beanh66 commented Jun 15, 2018

@jhadvig Got it, that makes sense to me on the order.

@@ -175,6 +176,13 @@ class App extends React.PureComponent {
<Route path="/k8s/ns/:ns/roles/:name/:rule/edit" exact component={EditRulePage} />
<Route path="/k8s/ns/:ns/roles" exact component={rolesListPage} />

<Route path="/k8s/cluster/secrets/new/:type" exact component={props => <CreateSecret {...props} kind="Secret" />} />
Copy link
Member

Choose a reason for hiding this comment

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

Can secrets be cluster scoped? I thought they had to be in a namespace

createProps = {
items: createHandler,
createLink(param) {
return param === 'yaml' ? href : `${href}/${param}`;
Copy link
Member

Choose a reason for hiding this comment

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

I'd call encodeURIComponent on param to be safe

@@ -0,0 +1,4 @@
.separator {
Copy link
Member

Choose a reason for hiding this comment

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

This class doesn't look specific to secrets. It should probably go in core. Suggest adding the .co- prefix, too.

Honestly, I would just remove the separator, though. I think it's better without it.

// source: 'Create Source Secret',
// image: 'Create Image Pull Secret',
// generic: 'Create Key/Value Secret',
webhook: 'Create Webhook Secret',
Copy link
Member

Choose a reason for hiding this comment

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

We only want to show the webhook secret option if this is an OpenShift cluster. You want connectToFlags(FLAGS.OPENSHIFT) to check

Cog.factory.ModifyLabels,
Cog.factory.ModifyAnnotations,
(kind, obj) => ({
label: `Duplicate ${kind.label}...`,
Copy link
Member

Choose a reason for hiding this comment

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

Interesting, is there a specific use case for copy that you had in mind?

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've seen that some of the sereources have the option to duplicate, but to be honest I wasnt sure if it should be available for secrets. Will put it away

stringData = secretsData;
this.setState({stringData});
}
changeSecretName (event) {
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest names onDataChanged and onNameChanged

return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
Copy link
Member

Choose a reason for hiding this comment

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

const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);

import * as React from 'react';

const generateSecret = () => {
//http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
Copy link
Member

Choose a reason for hiding this comment

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

super nit here, but can you put a space before the http in the comment :)

<fieldset disabled={!this.props.isCreate}>
<div className="form-group">
<label className="control-label">Secret Name</label>
<div className="modal-body__field">
Copy link
Member

Choose a reason for hiding this comment

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

Why do the classes have modal-body in them when they're not used in a modal?

e.preventDefault();
const { kind, metadata } = this.state.secret;
this.setState({ inProgress: true });
const newSecretObject = _.assign(this.state.secret, {stringData: this.state.stringData});
Copy link
Member

Choose a reason for hiding this comment

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

This mutates the original object, so is pretty much the same as

this.state.secret.stringData = this.state.stringData;

But I'd suggest

const { stringData } = this.state.stringData;
const newSecret = _.assign({}, this.state.secret, { stringData });

@spadgett
Copy link
Member

It looks like we need to update the integration tests for this change.

@jhadvig
Copy link
Member Author

jhadvig commented Jun 18, 2018

@spadgett I've updated the PR:

  • rewrote the subforms and create-secret into typescript - had to update button-bar.jsx because of that
  • updated the intergration-tests
  • only when creating webhook secret the form will be displayed, otherwise the YAML editor. The same applies for editing secrets, there only WebHookSecretKey key has to be present in the data.

Although I'm not sure why the tests are failing :-/

@spadgett
Copy link
Member

Ignore the ci/prow/* statuses.

Linting is failing, though:

go/src/github.com/openshift/console/frontend/public/components/utils/dropdown.jsx
  error Unexpected string concatenation prefer-template

@spadgett
Copy link
Member

You can always use yarn run lint to run the linter locally

@jhadvig
Copy link
Member Author

jhadvig commented Jun 19, 2018

@spadgett sorry for that ... thought that interpolating id="${itemKey}-link" wont cause lint to scream, but apparently id={${itemKey}-link} is the right form

@@ -85,7 +85,12 @@ describe('Kubernetes resource CRUD operations', () => {
}

it('displays a YAML editor for creating a new resource instance', async() => {
await crudView.createYAMLButton.click();
if (kind === 'Secret') {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of checking kind, can we check for the existence of #item-create? Then if we add similar buttons to other pages, the tests don't need to change.

@@ -16,7 +16,22 @@ data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm`);

const menuActions = Cog.factory.common;
const editInYaml = obj => {
if (obj.type === 'Opaque' && _.has(obj.data, 'WebHookSecretKey') && Object.keys(obj.data).length === 1) {
Copy link
Member

Choose a reason for hiding this comment

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

I would use

if (_.has(obj, 'data.WebHookSecretKey') && _.size(obj.data) === 1) {

The whole function could be simplified to

// Edit in YAML if not editing a webhook secret with one key.
const editInYaml = obj => !_.has(obj, 'data.WebHookSecretKey') || _size(obj.data) !== 1;

We should make the string WebHookSecretKey a const defined once somewhere that we reuse to avoid typos.

secret: secret,
inProgress: false,
type: secret.type,
stringData: _.mapValues(secret.data, (v) => window.atob(v)),
Copy link
Member

Choose a reason for hiding this comment

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

I think this can be

stringData: _.mapValues(secret.data, window.atob),

type: secret.type,
stringData: _.mapValues(secret.data, (v) => window.atob(v)),
};
this.onNameChanged = this.onNameChanged.bind(this);
Copy link
Member

Choose a reason for hiding this comment

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

You should bind onDataChanged here, too

e.preventDefault();
const { kind, metadata } = this.state.secret;
this.setState({ inProgress: true });
const newSecret = _.assign({}, this.state.secret, {stringData: this.state.stringData});
Copy link
Member

Choose a reason for hiding this comment

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

Does this include both data and stringData? We should only include stringData

const title = `${this.props.titleVerb} ${_.upperFirst(this.state.secretType)} Secret`;
const { saveButtonText } = this.props;

let explanation = 'Webhook secret allow you to authenticate a webhook trigger.';
Copy link
Member

Choose a reason for hiding this comment

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

'Webhook secrets allow you to authenticate a webhook trigger.'

const { saveButtonText } = this.props;

let explanation = 'Webhook secret allow you to authenticate a webhook trigger.';
let subform = <WebHookSecretSubform onChange={this.onDataChanged.bind(this)} stringData={this.state.stringData} />;
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice if the base edit component didn't need to know about the specific secret types. I wonder if we can't use a higher-order component here:

https://reactjs.org/docs/higher-order-components.html#use-hocs-for-cross-cutting-concerns


const BaseEditSecret = connect(null, {setActiveNamespace: UIActions.setActiveNamespace})(
(props: BaseEditSecretProps_) => <BaseEditSecret_ {...props} />
);
Copy link
Member

Choose a reason for hiding this comment

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

Can't this just be...

const BaseEditSecret = connect(null, {setActiveNamespace: UIActions.setActiveNamespace})(BaseEditSecret_);

Copy link
Member Author

Choose a reason for hiding this comment

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

No the props need to be passed explicitly from parent to child otherwise, yarn will scream that some properties does not exist:

Property 'fixed' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick<any, never>, ComponentState, never>...'.

Copy link
Member

Choose a reason for hiding this comment

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

Then I think we must have declared the types incorrectly somehow. We should figure out what's wrong.

Copy link
Member Author

@jhadvig jhadvig Jun 20, 2018

Choose a reason for hiding this comment

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

The issue is that the redux part of the code is in jsx an therefor is not typed, eg. ui-actions.js. I think until we type the redux part of the then codebase, which means rewriting it to TS, until then we need this as a workaround.

Was trying this workaround but due to issue described above it havent worked.

const generateSecret = () => {
// http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return s4()+s4()+s4()+s4();
Copy link
Member

Choose a reason for hiding this comment

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

nit: spaces before and after +

{props.errorMessage && <ErrorMessage message={props.errorMessage} />}
{injectDisabled(props.children, props.inProgress)}
{props.inProgress && <LoadingInline />}
{props.infoMessage && <InfoMessage message={props.infoMessage} />}
Copy link
Member

Choose a reason for hiding this comment

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

It's not clear to me why this change was 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.

There was an issue with the required properties for the ButtonBar

TS2322: Type '{ children: Element[]; errorMessage: any; inProgress: boolean; }' is not assignable to type 'IntrinsicAttributes & { children: any; className: any; errorMessage: any; infoMessage: any; inPro...'.
Type '{ children: Element[]; errorMessage: any; inProgress: boolean; }' is not assignable to type '{ children: any; className: any; errorMessage: any; infoMessage: any; inProgress: any; }'.
Property 'className' is missing in type '{ children: Element[]; errorMessage: any; inProgress: boolean; }'.
Version: typescript 2.7.2
Time: 12738ms

It was cause by the listed params in the class definition

export const ButtonBar = ({children, className, errorMessage, infoMessage, inProgress}) => {
...
}

Because of listing the parameters and not just setting the to props, all the listed params will be required, even if propTypes will declare that they are not.

Copy link
Member

Choose a reason for hiding this comment

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

Can you try adding an @type comment instead and mark className option?

https://github.com/openshift/console/blob/master/frontend/public/components/factory/list-page.jsx#L24


const determineSecretTypeAbstraction = (secret) => {
const { data } = secret;
if (_.has(data, 'WebHookSecretKey')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Style nit, but I think you will see something like:

return _.has(data, 'WebHookSecretKey') 
  ? 'webhook'
  : 'generic';

Throughout the app. If possible I think we should try to conform.

Copy link
Contributor

@benjaminapetersen benjaminapetersen left a comment

Choose a reason for hiding this comment

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

Just a few more minor tweaks!

class BaseEditSecret_ extends SafetyFirst<BaseEditSecretProps_, BaseEditSecretState_> {
constructor (props) {
super(props);
let existingData = _.pick(props.obj, ['metadata', 'data']);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can const existingData. It isn't changing.

this.save = this.save.bind(this);
}
onDataChanged (secretsData) {
let stringData = {...this.state.stringData};
Copy link
Contributor

Choose a reason for hiding this comment

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

const

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, you are defining stringData then immediately setting it as something else.

Could this just be:

this.setState({... secretsData});

this.setState({stringData});
}
onNameChanged (event) {
let secret = {...this.state.secret};
Copy link
Contributor

Choose a reason for hiding this comment

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

es6:

this.setState({
  ...this.state.secret,
  metadata: {
    name: event.target.value
  }
});

Copy link
Member Author

@jhadvig jhadvig Jun 19, 2018

Choose a reason for hiding this comment

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

That will just set the name in the metadata field, everything else will be removed when set. Tried:

this.setState({
  ...this.state.secret,
  metadata: {
    name: event.target.value
    ...this.state.secret.namespace,
  }
});

but thats not setting the name at all

(this.props.isCreate
? k8sCreate(ko, newSecret)
: k8sUpdate(ko, newSecret, metadata.namespace, newSecret.metadata.name)
).then(
Copy link
Contributor

Choose a reason for hiding this comment

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

Mind collapsing some parens? Ex: .then(() => {.

</Firehose>;

/* eslint-disable no-undef */
export type BaseEditSecretState_ = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the trailing underscore common? I haven't seen previously.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is, at least we use it in our codebase

Copy link
Contributor

Choose a reason for hiding this comment

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

Huh, ok neat.

Copy link
Member

Choose a reason for hiding this comment

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

Not typically for the types, though?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably not. If anything we could rename:

  • BaseEditSecret -> BaseEditSecretWrapper
  • BaseEditSecret_ -> BaseEditSecret

Copy link
Member

Choose a reason for hiding this comment

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

I think the names are good. Just wondering if we should have the underscore on the type definitions

import { SafetyFirst } from '../safety-first';
import { WebHookSecretSubform } from './subforms';

const determineSecretTypeAbstraction = (secret) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be fine to name this determineSecretType() or just secretType().

Copy link
Member Author

Choose a reason for hiding this comment

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

Secrets are a kind already have type field, and all the values that could return from that function will be just an type abstractions:

  • webhook
  • source
  • image
  • key/value

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok makes sense.

kind?: string,
isCreate: boolean,
titleVerb: string,
setActiveNamespace: any,
Copy link
Contributor

Choose a reason for hiding this comment

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

setActiveNamespace must be a function, correct? I believe this can be typed.

error?: any,
};

export type BaseEditSecretProps_ = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we eliminate the any types?
For example:

 obj: K8sResourceKind 
// ...
metadata: {
  name: string,
  // etc.
}

I think this file has some better type arbitrary examples.

Copy link
Member

Choose a reason for hiding this comment

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

fixed can really be any... It's just saying always use these properties. I don't think we can define that one.

We can use K8sResourceKind for 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.

Can we eliminate the any types?

no all the types have to be typed, otherwise yarn will screen, eg:

Property 'metadata' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick<BaseEditSecretProps_, "fixed" | "ki...'

Copy link
Member Author

Choose a reason for hiding this comment

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

Since some parts of codebase are not typed the its almost impossible not to use any

const title = `${this.props.titleVerb} ${_.upperFirst(this.state.secretType)} Secret`;
const { saveButtonText } = this.props;

let explanation = 'Webhook secret allow you to authenticate a webhook trigger.';
Copy link
Contributor

Choose a reason for hiding this comment

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

const explanation;
const subform;

@stevekuznetsov
Copy link

/test backend
/test frontend

@jhadvig
Copy link
Member Author

jhadvig commented Jun 19, 2018

@spadgett @benjaminapetersen comments addressed.
Regarding the Higher order composition comment I'm still looking into a way how that could be done, but not sure if it will be a benefit for us.

@spadgett
Copy link
Member

Regarding the Higher order composition comment I'm still looking into a way how that could be done, but not sure if it will be a benefit for us.

OK to leave for now, but it's something that we might explore before adding all of the dialogs when it's harder to change.

await crudView.createYAMLButton.click();
const exists = await crudView.createItemButton.isPresent();
if (exists) {
console.log('true');
Copy link
Member

Choose a reason for hiding this comment

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

Remove console.log here and just below

import { connect } from 'react-redux';
import { Link } from 'react-router-dom';

import { WEBHOOKSECRETKEY } from '../../const';
Copy link
Member

Choose a reason for hiding this comment

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

I would probably just export it in this file.

export const WebHookSecretKey = 'WebHookSecretKey';

@@ -0,0 +1,49 @@
import * as React from 'react';
Copy link
Member

Choose a reason for hiding this comment

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

These components are going to be so tightly coupled to create secret, I would keep them in the same file. Then you don't need to export them since they're internal to the implementation.

export class WebHookSecretSubform extends React.Component<WebHookSecretSubformProps, WebHookSecretSubformState> {
constructor(props) {
super(props);
this.state = {WebHookSecretKey: this.props.stringData.WebHookSecretKey || ''};
Copy link
Member

Choose a reason for hiding this comment

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

nit: I'd call this webhookSecretKey. State properties usually begin with lowercase letters

Copy link
Member Author

Choose a reason for hiding this comment

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

true but this key is kinda specific, since it the only one from the known secret keys that starts with uppercase. Also the this.state of WebHookSecretSubform is mapped to this.state.secret.stringData of BaseEditSecret_, therefor we would need to handle the name conversion somewhere else eventually.

@@ -21,6 +21,7 @@ const InfoMessage = ({message}) => <div className="alert alert-info"><span class
// NOTE: DO NOT use <a> elements within a ButtonBar.
// They don't support the disabled attribute, and therefore
// can't be disabled during a pending promise/request.
/** @type {React.SFC<{children: any, className?: string, errorMessage?: string, infoMessage?: string, inProgress: boolean}}>} */
Copy link
Member

Choose a reason for hiding this comment

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

👍


const BaseEditSecret = connect(null, {setActiveNamespace: UIActions.setActiveNamespace})(
(props: BaseEditSecretProps_) => <BaseEditSecret_ {...props} />
);
Copy link
Member

Choose a reason for hiding this comment

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

Then I think we must have declared the types incorrectly somehow. We should figure out what's wrong.

</Firehose>;

/* eslint-disable no-undef */
export type BaseEditSecretState_ = {
Copy link
Member

Choose a reason for hiding this comment

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

Not typically for the types, though?


/* eslint-disable no-undef */
export type BaseEditSecretState_ = {
secretType?: string,
Copy link
Member

Choose a reason for hiding this comment

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

This would be better as an enum

@beanh66
Copy link

beanh66 commented Jun 20, 2018

@jhadvig Do you mind adding a screenshot of the latest? Thanks!

@jhadvig
Copy link
Member Author

jhadvig commented Jun 20, 2018

@beanh66 there haven't been much of a changes, just wording in the form:
1
2
3

@beanh66
Copy link

beanh66 commented Jun 20, 2018

@jhadvig Thanks! Question...should the last screen say "Edit Secret" as the title? Wondering why we need Generic.

@jhadvig
Copy link
Member Author

jhadvig commented Jun 20, 2018

@beanh66 sorry for that, accidentally d'n'd old screen there.. the title should reflect the secret type, in this case it should be - Edit Webhook Secret, the same for create page - Create Webhook Secret

@jhadvig
Copy link
Member Author

jhadvig commented Jun 20, 2018

@spadgett comments addressed and comments added. PTAL

Copy link
Member

@spadgett spadgett left a comment

Choose a reason for hiding this comment

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

👍

Thanks for your patience, @jhadvig. LGTM

@spadgett
Copy link
Member

/lgtm
/retest

I suspect the ci/prow/* jobs are broken again, but let's check

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

@jhadvig: The following tests failed, say /retest to rerun them all:

Test name Commit Details Rerun command
ci/prow/crud a6383dd link /test crud
ci/prow/alm a6383dd link /test alm
ci/prow/performance a6383dd link /test performance
ci/prow/backend 33d1cba link /test backend
ci/prow/frontend 33d1cba link /test frontend

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@spadgett spadgett merged commit add3636 into openshift:master Jun 20, 2018
@jhadvig
Copy link
Member Author

jhadvig commented Jun 20, 2018

Thanks @spadgett much appreciated ! :)

christianvogt pushed a commit to christianvogt/console that referenced this pull request May 16, 2019
TimothyAsirJeyasing pushed a commit to TimothyAsirJeyasing/console that referenced this pull request Aug 3, 2022
…w_shared

Migration: Add shared components
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm Indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.