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

MMT-3417: As a MMT dev, I want to be able to CRUD UMM-V records in CMR GraphQL #81

Merged
merged 12 commits into from
Nov 17, 2023
12 changes: 6 additions & 6 deletions src/cmr/concepts/concept.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,12 +367,12 @@ export default class Concept {
this.logKeyRequest(requestedKeys, 'ingest')

// Construct the promise that will ingest data into CMR
this.response = cmrIngest(
this.getConceptType(),
params,
providedHeaders,
this.ingestPath
)
this.response = cmrIngest({
conceptType: this.getConceptType(),
data: params,
headers: providedHeaders,
ingestPath: this.ingestPath
})
}

/**
Expand Down
24 changes: 16 additions & 8 deletions src/cmr/concepts/draft.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ export default class Draft extends Concept {

getPermittedPublishKeys() {
return [
'nativeId'
'nativeId',
'collectionConceptId'
]
}

Expand Down Expand Up @@ -219,12 +220,19 @@ export default class Draft extends Concept {

this.logKeyRequest(requestedKeys, 'ingest')

// Construct the promise that will ingest data into CMR
this.response = cmrIngest(
this.getConceptType(),
pick(params, this.getPermittedPublishKeys()),
permittedHeaders,
this.publishPath
)
const { collectionConceptId } = params
delete params.collectionConceptId

const prepDataForCmr = {
...pick(params, this.getPermittedPublishKeys()),
'collection-concept-id': collectionConceptId
}
// Calling cmrIngest directly because the ingest path is different for publish is different.
this.response = cmrIngest({
macrouch marked this conversation as resolved.
Show resolved Hide resolved
conceptType: this.getConceptType(),
data: prepDataForCmr,
headers: permittedHeaders,
ingestPath: this.publishPath
})
}
}
9 changes: 8 additions & 1 deletion src/cmr/concepts/subscription.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import camelcaseKeys from 'camelcase-keys'
import { uniq } from 'lodash'
import { mergeParams } from '../../utils/mergeParams'

import { pickIgnoringCase } from '../../utils/pickIgnoringCase'
import Concept from './concept'
Expand Down Expand Up @@ -113,6 +115,11 @@ export default class Subscription extends Concept {
// eslint-disable-next-line no-param-reassign
data.metadataSpecification = this.metadataSpecification

super.ingest(data, requestedKeys, permittedHeaders)
const prepDataForCmr = camelcaseKeys(mergeParams(data), {
pascalCase: true,
exclude: ['nativeId']
})

super.ingest(prepDataForCmr, requestedKeys, permittedHeaders)
}
}
4 changes: 4 additions & 0 deletions src/cmr/concepts/variable.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export default class Variable extends Concept {
*/
constructor(headers, requestInfo, params) {
super('variables', headers, requestInfo, params)

const { providerId } = params

this.ingestPath = `providers/${providerId}/variables`
}

/**
Expand Down
78 changes: 78 additions & 0 deletions src/datasources/__tests__/draft.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -671,3 +671,81 @@ describe('draft#publish', () => {
).rejects.toThrow(Error)
})
})

describe('variableDraft#publish', () => {
const OLD_ENV = process.env

beforeEach(() => {
jest.resetAllMocks()

jest.restoreAllMocks()

process.env = { ...OLD_ENV }

process.env.cmrRootUrl = 'http://example.com'

// Default requestInfo
requestInfo = {
name: 'publishDraft',
alias: 'publishDraft',
args: {
draftConceptId: 'VD100000-EDSC',
nativeId: 'mock-native-id',
ummVersion: '1.0.0',
collectionConceptId: ''
},
fieldsByTypeName: {
PublishDraftMutationResponse: {
conceptId: {
name: 'conceptId',
alias: 'conceptId',
args: {},
fieldsByTypeName: {}
},
revisionId: {
name: 'revisionId',
alias: 'revisionId',
args: {},
fieldsByTypeName: {}
}
}
}
}
})

afterEach(() => {
process.env = OLD_ENV
})

test('returns the parsed draft results', async () => {
nock(/example/)
.defaultReplyHeaders({
'CMR-Request-Id': 'abcd-1234-efgh-5678'
})
.put(/ingest\/publish\/VD100000-EDSC\/mock-native-id/, JSON.stringify({
'collection-concept-id': 'CD100000-EDSC'
}))
.reply(201, {
'concept-id': 'V100000-EDSC',
'revision-id': '1'
})

const response = await draftSourcePublish({
draftConceptId: 'VD100000-EDSC',
nativeId: 'mock-native-id',
ummVersion: '1.0.0',
collectionConceptId: 'CD100000-EDSC'

}, {
headers: {
'Client-Id': 'eed-test-graphql',
'CMR-Request-Id': 'abcd-1234-efgh-5678'
}
}, requestInfo)

expect(response).toEqual({
conceptId: 'V100000-EDSC',
revisionId: '1'
})
})
})
110 changes: 103 additions & 7 deletions src/datasources/__tests__/variable.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import nock from 'nock'

import variableDatasource from '../variable'
import {
deleteVariable as variableSourceDelete,
fetchVariables as variableSourceFetch
} from '../variable'

let requestInfo

Expand Down Expand Up @@ -108,7 +111,7 @@ describe('variable', () => {
}]
})

const response = await variableDatasource({}, {
const response = await variableSourceFetch({}, {
headers: {
'Client-Id': 'eed-test-graphql',
'CMR-Request-Id': 'abcd-1234-efgh-5678'
Expand Down Expand Up @@ -146,7 +149,7 @@ describe('variable', () => {
}]
})

const response = await variableDatasource({}, {
const response = await variableSourceFetch({}, {
headers: {
'Client-Id': 'eed-test-graphql',
'CMR-Request-Id': 'abcd-1234-efgh-5678'
Expand Down Expand Up @@ -180,7 +183,7 @@ describe('variable', () => {
}]
})

const response = await variableDatasource({}, {
const response = await variableSourceFetch({}, {
headers: {
'Client-Id': 'eed-test-graphql',
'CMR-Request-Id': 'abcd-1234-efgh-5678'
Expand Down Expand Up @@ -212,7 +215,7 @@ describe('variable', () => {
}]
})

const response = await variableDatasource({
const response = await variableSourceFetch({
params: {
concept_id: 'V100000-EDSC'
}
Expand Down Expand Up @@ -287,7 +290,7 @@ describe('variable', () => {
}]
})

const response = await variableDatasource({
const response = await variableSourceFetch({
params: {
conceptId: 'V100000-EDSC'
}
Expand Down Expand Up @@ -318,7 +321,7 @@ describe('variable', () => {
})

await expect(
variableDatasource({
variableSourceFetch({
params: {
conceptId: 'V100000-EDSC'
}
Expand All @@ -331,3 +334,96 @@ describe('variable', () => {
).rejects.toThrow(Error)
})
})

describe('variable#delete', () => {
const OLD_ENV = process.env

beforeEach(() => {
jest.resetAllMocks()

jest.restoreAllMocks()

process.env = { ...OLD_ENV }

process.env.cmrRootUrl = 'http://example-cmr.com'

// Default requestInfo
requestInfo = {
name: 'deleteVariable',
alias: 'deleteVariable',
args: {
conceptId: 'V100000-EDSC',
nativeId: 'test-guid'
},
fieldsByTypeName: {
VariableMutationResponse: {
conceptId: {
name: 'conceptId',
alias: 'conceptId',
args: {},
fieldsByTypeName: {}
},
revisionId: {
name: 'revisionId',
alias: 'revisionId',
args: {},
fieldsByTypeName: {}
}
}
}
}
})

afterEach(() => {
process.env = OLD_ENV
})

test('returns the CMR results', async () => {
nock(/example-cmr/)
.defaultReplyHeaders({
'CMR-Request-Id': 'abcd-1234-efgh-5678'
})
.delete(/ingest\/providers\/EDSC\/variables\/test-guid/)
.reply(201, {
'concept-id': 'V100000-EDSC',
'revision-id': '1'
})

const response = await variableSourceDelete({
nativeId: 'test-guid',
providerId: 'EDSC'
}, {
headers: {
'Client-Id': 'eed-test-graphql',
'CMR-Request-Id': 'abcd-1234-efgh-5678'
}
}, requestInfo)

expect(response).toEqual({
conceptId: 'V100000-EDSC',
revisionId: '1'
})
})

test('catches errors received from cmrDelete', async () => {
nock(/example-cmr/)
.delete(/ingest\/providers\/EDSC\/variables\/test-guid/)
.reply(500, {
errors: ['HTTP Error']
}, {
'cmr-request-id': 'abcd-1234-efgh-5678'
})

await expect(
variableSourceDelete({
nativeId: 'test-guid',
providerId: 'EDSC'
}, {
headers: {
'Client-Id': 'eed-test-graphql',
'CMR-Request-Id': 'abcd-1234-efgh-5678'
}
}, requestInfo)
).rejects.toThrow(Error)
})
})
23 changes: 22 additions & 1 deletion src/datasources/variable.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import variableKeyMap from '../utils/umm/variableKeyMap.json'

import Variable from '../cmr/concepts/variable'

export default async (params, context, parsedInfo) => {
export const fetchVariables = async (params, context, parsedInfo) => {
const { headers } = context

const requestInfo = parseRequestedFields(parsedInfo, variableKeyMap, 'variable')
Expand All @@ -20,3 +20,24 @@ export default async (params, context, parsedInfo) => {
// Return a formatted JSON response
return variable.getFormattedResponse()
}

export const deleteVariable = async (args, context, parsedInfo) => {
const { headers } = context

const requestInfo = parseRequestedFields(parsedInfo, variableKeyMap, 'variable')

const {
ingestKeys
} = requestInfo

const variable = new Variable(headers, requestInfo, args)

// Contact CMR
variable.delete(args, ingestKeys, headers)

// Parse the response from CMR
await variable.parseDelete(requestInfo)

// Return a formatted JSON response
return variable.getFormattedDeleteResponse()
}
10 changes: 8 additions & 2 deletions src/graphql/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ import orderOptionSource from '../datasources/orderOption'
import serviceDraftSource from '../datasources/serviceDraft'
import toolDraftSource from '../datasources/toolDraft'
import variableDraftSource from '../datasources/variableDraft'
import variableSource from '../datasources/variable'

import { deleteTool as toolSourceDelete, fetchTools as toolSourceFetch } from '../datasources/tool'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

try to split this


Copy link
Contributor Author

Choose a reason for hiding this comment

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

remove extra line

import {
deleteService as serviceSourceDelete,
fetchServices as serviceSourceFetch
} from '../datasources/service'

import {
deleteVariable as variableSourceDelete,
fetchVariables as variableSourceFetch
} from '../datasources/variable'

import {
deleteSubscription as subscriptionSourceDelete,
fetchSubscription as subscriptionSourceFetch,
Expand Down Expand Up @@ -170,7 +175,8 @@ export default startServerAndCreateLambdaHandler(
toolSourceDelete,
toolSourceFetch,
variableDraftSource,
variableSource
variableSourceDelete,
variableSourceFetch
},
headers: requestHeaders,
collectionLoader: new DataLoader(getCollectionsById, { cacheKeyFn: (obj) => obj.conceptId })
Expand Down
Loading