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

fix hardcoded references to kubeapps namespace in dashboard #425

Merged

Conversation

prydonius
Copy link
Contributor

@prydonius prydonius commented Aug 2, 2018

also moves config into the redux store

fixes #415

@prydonius prydonius changed the title fixes #415 fix hardcoded references to kubeapps namespace in dashboard Aug 2, 2018
@prydonius prydonius added the component/ui Issue related to kubeapps UI label Aug 2, 2018
chartVersion: IChartVersion,
values?: string,
) {
const chartAttrs = chartVersion.relationships.chart.data;
const repo = await AppRepository.get(chartAttrs.repo.name);
const repo = await AppRepository.get(chartAttrs.repo.name, kubeappsNamespace);
const auth = repo.spec.auth;
Copy link
Contributor

Choose a reason for hiding this comment

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

Not from this patch but just pointing out inconsistent usage of es6 destructuring.

const { auth } = repo.spec;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I fix this in this PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

No

import { IAppRepository, IAppRepositoryList } from "./types";

export class AppRepository {
public static async list() {
const { data } = await axios.get<IAppRepositoryList>(await AppRepository.getResourceLink());
public static async list(namespace: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

is this namespace a kubeappsNamespace?

Copy link
Contributor Author

@prydonius prydonius Aug 3, 2018

Choose a reason for hiding this comment

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

yes, but I don't think AppRepository should really know about that, it just cares about what namespace to request from in the API

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed, thanks for the explanation.

return `${AppRepository.APIEndpoint}/namespaces/${namespace}/apprepositories${
name ? `/${name}` : ""
}`;
private static getResourceLink(namespace?: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please add a comment on why this URI resolution is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We're doing this in other classes so it's a common model and not something specific for this class

@@ -19,11 +19,12 @@ export class App {
public static async create(
releaseName: string,
Copy link
Contributor

Choose a reason for hiding this comment

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

So this shared directory is like a shared set of models?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, correct. We try to keep all the API related methods here and not in the actual actions.

@@ -3,6 +3,7 @@ import { IServiceCatalogState } from "../reducers/catalog";
import { IFunctionState } from "../reducers/functions";
import { INamespaceState } from "../reducers/namespace";
import { IAppRepositoryState } from "../reducers/repos";
import { IConfig } from "./Config";
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the reason for the I prefix?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -1,20 +1,15 @@
import axios from "axios";

interface IConfig {
export interface IConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a comment saying that this is the kubeapps configuration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

+1 will do

namespace: string;
}

export default class Config {
public static async getConfig() {
if (Config.config) {
return Config.config;
}
const url = `${Config.APIEndpoint}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

do you need the backticks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 will fix

@@ -14,6 +14,7 @@ import AppView from "./AppViewContainer";
import ChartList from "./ChartListContainer";
import ChartView from "./ChartViewContainer";
import ClassListContainer from "./ClassListContainer";
import { ClassViewContainer } from "./ClassView";
Copy link
Contributor

Choose a reason for hiding this comment

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

what for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved this for consistency, the package imports are separated from local imports

import { IConfig } from "../shared/Config";

const initialState: IConfig = {
namespace: "default",
Copy link
Contributor

Choose a reason for hiding this comment

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

do we really want a default? I am wondering if this could have side-effects in the case that there are problems while retrieving the value from the config endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's possible that there's a race condition here, yes. I need to look into this more.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed, PTAL @migmartri

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

an alternative solution would be to add an env var in the dashboard container with the namespace of the pod:

        - name: KUBEAPPS_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace

I think it will be easier to read an env var (it's synchronous) rather than getting the namespace from a configmap (that can be misconfigured).

That wouldn't work if the dashboard is in a different namespace than the rest of Kubeapps but I don't think that's a possibility, isn't it?

namespace={RequiredRBACRoles.namespace || ""}
roles={[RequiredRBACRoles]}
action={`list app repositories`}
namespace={this.requiredRBACRoles().namespace || ""}
Copy link
Contributor

Choose a reason for hiding this comment

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

namespace={this.props.namespace} is a bit more simple

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

}

private static config: IConfig;
private static APIEndpoint: string = "/config.json";
Copy link
Contributor

@andresmgot andresmgot Aug 3, 2018

Choose a reason for hiding this comment

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

It's not related to this PR but this is a bit confusing (using axios.get with an "URL" to read a local file). Mostly because this method is now unnecessary async.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@andresmgot perhaps you're misunderstanding this a bit? The nginx server serves the config.json file, it's not embedded in the React application. I'm not sure what you mean by local file, at some point the React app has to fetch this from the server.

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 that the key here is that the React app is just a bundle of static files so AFAIK there is no way of exposing this env variable without triggering a build (via webpack) at deployment time.

If there was a way for Nginx to expose this env variable as a header that could be an alternative. Although I have not found any example nor insights on how to achieve so.

Copy link
Contributor

Choose a reason for hiding this comment

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

true, completely misunderstood from my side. Sorry!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No problem, thanks for asking!

@prydonius
Copy link
Contributor Author

an alternative solution would be to add an env var in the dashboard container with the namespace of the pod

Hmm I'm not sure how we'd read the env var and respond with that from the nginx server, we could use an initContainer that creates the config.json file using that env var, but that might make it more difficult to add more configuration later. @migmartri what do you think?

@prydonius
Copy link
Contributor Author

@migmartri @andresmgot review addressed, PTAL!

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

we could use an initContainer that creates the config.json file using that env var, but that might make it more difficult to add more configuration later

Agree, nvm. LGTM right now.

Copy link
Contributor

@migmartri migmartri 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 the changes.

))}
</Layout>
</ConnectedRouter>
<ConfigLoaderContainer>
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice.

switch (action.type) {
case getType(actions.config.requestConfig):
return initialState;
case getType(actions.config.receiveConfig):
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor comment. Shouldn't this be receivedConfig instead of receiveConfig? Just feels like receiveConfig is setting the intention instead of the result.


const configReducer = (state: IConfigState = initialState, action: ConfigAction): IConfigState => {
switch (action.type) {
case getType(actions.config.requestConfig):
Copy link
Contributor

Choose a reason for hiding this comment

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

Not for this patch but in general we should start thinking of error handling so we do not run into cases like this one #433

chartVersion: IChartVersion,
values?: string,
) {
const chartAttrs = chartVersion.relationships.chart.data;
const repo = await AppRepository.get(chartAttrs.repo.name);
const repo = await AppRepository.get(chartAttrs.repo.name, kubeappsNamespace);
const auth = repo.spec.auth;
Copy link
Contributor

Choose a reason for hiding this comment

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

No

import { IAppRepository, IAppRepositoryList } from "./types";

export class AppRepository {
public static async list() {
const { data } = await axios.get<IAppRepositoryList>(await AppRepository.getResourceLink());
public static async list(namespace: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed, thanks for the explanation.

@prydonius prydonius merged commit b86b8d7 into vmware-tanzu:master Aug 6, 2018
@prydonius prydonius deleted the 415-fix-hardcoded-references branch August 6, 2018 22:35
andresmgot pushed a commit to andresmgot/installer that referenced this pull request Aug 13, 2018
…anzu#425)

* add config to redux store

* use kubeapps install namespace from redux config store for AppRepo API calls

* ensure config is loaded before loading app

* comment for IConfig interface

* remove unnecessary string interpolation

* use kubeappsNamespace prop directly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/ui Issue related to kubeapps UI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix hardcoded references to kubeapps namespace in Kubeapps UI
3 participants