Add flavor fetching via Nova API
This patch support for fetching Nova flavors via its REST API. We're including all of the necessary pieces including reducer, selector, etc. Change-Id: I9535fa8254039ef564d62b653934267b2380ce7c Depends-On: Ic6df58947bb2cb1e183b5c88ed8d287191e5ee07
This commit is contained in:
parent
1b1c0b8471
commit
3b91169acd
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { normalize } from 'normalizr';
|
||||
|
||||
import { flavorSchema } from '../normalizrSchemas/flavors';
|
||||
import { handleErrors } from './ErrorActions';
|
||||
import NovaApiService from '../services/NovaApiService';
|
||||
import FlavorsConstants from '../constants/FlavorsConstants';
|
||||
|
||||
export default {
|
||||
fetchFlavorsPending() {
|
||||
return {
|
||||
type: FlavorsConstants.FETCH_FLAVORS_PENDING
|
||||
};
|
||||
},
|
||||
|
||||
fetchFlavorsSuccess(flavors) {
|
||||
return {
|
||||
type: FlavorsConstants.FETCH_FLAVORS_SUCCESS,
|
||||
payload: flavors
|
||||
};
|
||||
},
|
||||
|
||||
fetchFlavorsFailed() {
|
||||
return {
|
||||
type: FlavorsConstants.FETCH_FLAVORS_FAILED
|
||||
};
|
||||
},
|
||||
|
||||
fetchFlavors() {
|
||||
return dispatch => {
|
||||
dispatch(this.fetchFlavorsPending());
|
||||
dispatch(NovaApiService.getFlavors())
|
||||
.then(response => {
|
||||
const flavors = normalize(response.flavors, [flavorSchema]).entities
|
||||
.flavors;
|
||||
dispatch(this.fetchFlavorsSuccess(flavors));
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch(handleErrors(error, 'Flavors could not be loaded.'));
|
||||
dispatch(this.fetchFlavorsFailed());
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import keyMirror from 'keymirror';
|
||||
|
||||
export default keyMirror({
|
||||
FETCH_FLAVORS_PENDING: null,
|
||||
FETCH_FLAVORS_FAILED: null,
|
||||
FETCH_FLAVORS_SUCCESS: null
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Map, Record } from 'immutable';
|
||||
|
||||
export const FlavorsState = Record({
|
||||
isFetching: false,
|
||||
isLoaded: false,
|
||||
flavors: Map()
|
||||
});
|
||||
|
||||
export const Flavor = Record({
|
||||
name: undefined,
|
||||
id: undefined
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { schema } from 'normalizr';
|
||||
|
||||
export const flavorSchema = new schema.Entity(
|
||||
'flavors',
|
||||
{},
|
||||
{ idAttribute: 'id' }
|
||||
);
|
|
@ -20,6 +20,7 @@ import { reducer as formReducer } from 'redux-form';
|
|||
import appConfig from './appConfig';
|
||||
import environmentConfigurationReducer from './environmentConfigurationReducer';
|
||||
import filtersReducer from './filtersReducer';
|
||||
import flavorsReducer from './flavorsReducer';
|
||||
import i18nReducer from './i18nReducer';
|
||||
import loggerReducer from './loggerReducer';
|
||||
import loginReducer from './loginReducer';
|
||||
|
@ -39,6 +40,7 @@ const appReducer = combineReducers({
|
|||
environmentConfiguration: environmentConfigurationReducer,
|
||||
executions: workflowExecutionsReducer,
|
||||
filters: filtersReducer,
|
||||
flavors: flavorsReducer,
|
||||
i18n: i18nReducer,
|
||||
logger: loggerReducer,
|
||||
login: loginReducer,
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
import FlavorsConstants from '../constants/FlavorsConstants';
|
||||
import { FlavorsState, Flavor } from '../immutableRecords/flavors';
|
||||
|
||||
const initialState = new FlavorsState();
|
||||
|
||||
export default function flavorsReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case FlavorsConstants.FETCH_FLAVORS_PENDING:
|
||||
return state.set('isFetching', true);
|
||||
|
||||
case FlavorsConstants.FETCH_FLAVORS_FAILED:
|
||||
return state.set('isFetching', false);
|
||||
|
||||
case FlavorsConstants.FETCH_FLAVORS_SUCCESS: {
|
||||
const flavors = fromJS(action.payload).map(flavor => new Flavor(flavor));
|
||||
return state
|
||||
.set('flavors', flavors)
|
||||
.set('isLoaded', true)
|
||||
.set('isFetching', false);
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
const flavors = state => state.flavors;
|
||||
|
||||
export const getFlavors = createSelector([flavors], flavors =>
|
||||
flavors.flavors.sortBy(f => f.name)
|
||||
);
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Copyright 2018 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
import when from 'when';
|
||||
|
||||
import { AuthenticationError, NovaApiError, ConnectionError } from './errors';
|
||||
import { getAuthTokenId, getServiceUrl } from '../selectors/auth';
|
||||
|
||||
class NovaApiService {
|
||||
defaultRequest(path, additionalAttributes) {
|
||||
return (dispatch, getState) =>
|
||||
axios(
|
||||
Object.assign(
|
||||
{
|
||||
baseURL: getServiceUrl(getState(), 'nova'),
|
||||
url: path,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Auth-Token': getAuthTokenId(getState())
|
||||
}
|
||||
},
|
||||
additionalAttributes
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getFlavors() {
|
||||
return dispatch =>
|
||||
dispatch(this.defaultRequest('/flavors'))
|
||||
.then(response => response.data)
|
||||
.catch(handleErrors);
|
||||
}
|
||||
}
|
||||
|
||||
const handleErrors = e => {
|
||||
if (e.response && e.response.status === 401) {
|
||||
return when.reject(new AuthenticationError(e));
|
||||
} else if (e.response) {
|
||||
return when.reject(new NovaApiError(e));
|
||||
} else if (e.request) {
|
||||
return when.reject(
|
||||
new ConnectionError('Connection to Nova API could not be established', e)
|
||||
);
|
||||
} else {
|
||||
return when.reject(e);
|
||||
}
|
||||
};
|
||||
|
||||
export default new NovaApiService();
|
|
@ -84,6 +84,12 @@ class KeystoneApiError extends BaseAxiosError {
|
|||
}
|
||||
}
|
||||
|
||||
class NovaApiError extends BaseAxiosError {
|
||||
constructor(e) {
|
||||
super('NovaApiError', e.response.data.error.message, e);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
BaseAxiosError,
|
||||
AuthenticationError,
|
||||
|
@ -94,5 +100,6 @@ export {
|
|||
IronicApiError,
|
||||
IronicInspectorApiError,
|
||||
HeatApiError,
|
||||
KeystoneApiError
|
||||
KeystoneApiError,
|
||||
NovaApiError
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue