Related
I need help with jq syntax on how to return the Gitlab job ID if it contains an artifact. The JSON output looks like this (removed a lot of unrelated info from it and added [...]):
[{
"id": 3219589880,
"status": "success",
"stage": "test",
"name": "job_with_no_artifact",
"ref": "main",
"tag": false,
"coverage": null,
"allow_failure": false,
"created_at": "2022-10-24T18:21:25.119Z",
"started_at": "2022-10-24T18:21:25.986Z",
"finished_at": "2022-10-24T18:21:38.464Z",
"duration": 12.478682,
"queued_duration": 0.499786,
"user": {
"id": 123456789,
[...]
},
"commit": {
"id": "5e0e1f287d20daf2036a3ca71c656dce55999265",
[...]
"pipeline": {
"id": 123456789,
[...]
"project": {
"ci_job_token_scope_enabled": false
},
"artifacts": [],
"runner": {
"id": 12270859,
[...]
},
"artifacts_expire_at": null,
"tag_list": []
}, {
"id": 3219589878,
"status": "success",
"stage": "test",
"name": "create_artifact_job_2",
"ref": "main",
"tag": false,
"coverage": null,
"allow_failure": false,
"created_at": "2022-10-24T18:21:25.111Z",
"started_at": "2022-10-24T18:21:25.922Z",
"finished_at": "2022-10-24T18:21:39.090Z",
"duration": 13.168405,
"queued_duration": 0.464364,
"user": {
"id": 123456789,
[...]
},
"commit": {
"id": "5e0e1f287d20daf2036a3ca71c656dce55999265",
[...]
},
"pipeline": {
"id": 675641982,
[...],
"project": {
"ci_job_token_scope_enabled": false
},
"artifacts_file": {
"filename": "artifacts.zip",
"size": 223
},
"artifacts": [{
"file_type": "archive",
"size": 223,
"filename": "artifacts.zip",
"file_format": "zip"
}, {
"file_type": "metadata",
"size": 153,
"filename": "metadata.gz",
"file_format": "gzip"
}],
"runner": {
"id": 12270845,
[...]
},
"artifacts_expire_at": "2022-10-25T18:21:35.859Z",
"tag_list": []
}, {
"id": 3219589876,
"status": "success",
"stage": "test",
"name": "create_artifact_job_1",
"ref": "main",
"tag": false,
"coverage": null,
"allow_failure": false,
"created_at": "2022-10-24T18:21:25.103Z",
"started_at": "2022-10-24T18:21:25.503Z",
"finished_at": "2022-10-24T18:21:41.407Z",
"duration": 15.904028,
"queued_duration": 0.098837,
"user": {
"id": 123456789,
[...]
},
"commit": {
"id": "5e0e1f287d20daf2036a3ca71c656dce55999265",
[...]
},
"pipeline": {
"id": 123456789,
[...]
},
"web_url": "WEB_URL",
"project": {
"ci_job_token_scope_enabled": false
},
"artifacts_file": {
"filename": "artifacts.zip",
"size": 217
},
"artifacts": [{
"file_type": "archive",
"size": 217,
"filename": "artifacts.zip",
"file_format": "zip"
}, {
"file_type": "metadata",
"size": 152,
"filename": "metadata.gz",
"file_format": "gzip"
}],
"runner": {
"id": 12270857,
},
"artifacts_expire_at": "2022-10-25T18:21:37.808Z",
"tag_list": []
}]
I've been trying to do either of the following using jQ:
Either:
Check if artifacts_file key exists in each iteration and if it does return the (job) id (so .[].id)
Check if artifacts array is empty in each iteration and if it is empty return the (job) id.
In both cases I'm able to do the first part but I am not sure how to return the .id key.
Related stackoverflow questions that I've been trying to utilize and adapt to my case:
jq - return array value if its length is not null
How to check for presence of 'key' in jq before iterating over the values
What I have so far: jq '[.[].artifacts[]|select(length > 0)] | .[]' which returns all the artifacts found (but it doesn't contain the .id of the job).
Checking the existence of a field using has:
.[] | select(has("artifacts_file")).id
3219589878
3219589876
Demo
Checking if a field is an empty array by comparing it to []:
.[] | select(.artifacts == []).id
3219589880
Demo
need help to parse the JSON data received from Oracle Integration Cloud. The expected output is mentioned below alongwith the command i am trying to use.
JQ command
jq '[{id: .id},{integrations: [.integrations[]|{code: .code, version: .version, dependencies: .dependencies|{connections: .connections[]|{id: .id, status: .status}}, .dependencies|{lookups: .lookups}}]}]' output.json
Error :
jq: error: syntax error, unexpected FIELD (Unix shell quoting issues?) at , line 1:
[{id: .id},{integrations: [.integrations[]|{code: .code, version: .version, dependencies: .dependencies|{connections: .connections[]|{id: .id, status: .status}}, .dependencies|{lookups: .lookups}}]}]
Note : If i run below command to fetch only connections data it works fine
jq '[{id: .id},{integrations: [.integrations[]|{code: .code, version: .version, dependencies: .dependencies|{connections: .connections[]|{id: .id, status: .status}}}]}]' output.json
Expected Output:
[
{
"id": "SAMPLE_PACKAGE"
},
{
"integrations": [
{
"code": "HELLO_INTEGRATION",
"version": "01.00.0000",
"dependencies": {
"connections": {
"id": "HELLO_WORLD1",
"status": "CONFIGURED"
}
}
},
{
"code": "HELLO_INTEGRATIO_LOOKUP",
"version": "01.00.0000",
"dependencies": {
"connections": {
"id": "HELLO_WORLD1",
"status": "CONFIGURED"
},
"lookups": {
"name": "COMMON_LOOKUP_VARIABLES",
"status": "CONFIGURED"
}
}
},
{
"code": "HI_INTEGRATION",
"version": "01.00.0000",
"dependencies": {
"connections": {
"id": "HELLO_WORLD1",
"status": "CONFIGURED"
}
}
}
]
}
]
output.json file contains
{
"bartaType": "DEVELOPED",
"countOfIntegrations": 3,
"id": "SAMPLE_PACKAGE",
"integrations": [
{
"code": "HELLO_INTEGRATION",
"dependencies": {
"connections": [
{
"id": "HELLO_WORLD1",
"lockedFlag": false,
"name": "Hello World1",
"role": "SOURCE",
"status": "CONFIGURED",
"type": "rest",
"usage": 6
}
]
},
"description": "",
"eventSubscriptionFlag": false,
"filmstrip": [
{
"code": "HELLO_WORLD1",
"iconUrl": "/images/rest/rest_icon_46.png",
"name": "Hello World1",
"role": "SOURCE",
"status": "CONFIGURED"
}
],
"id": "HELLO_INTEGRATION|01.00.0000",
"lockedFlag": false,
"name": "HELLO_INTEGRATION",
"pattern": "Orchestration",
"patternDescription": "Map Data",
"payloadTracingEnabledFlag": true,
"publishFlag": false,
"scheduleApplicable": false,
"scheduleDefined": false,
"status": "ACTIVATED",
"style": "FREEFORM",
"styleDescription": "Orchestration",
"tempCopyExists": false,
"tracingEnabledFlag": true,
"version": "01.00.0000",
"warningMsg": "ACTIVATE_PUBLISH_NO_CONN"
},
{
"code": "HELLO_INTEGRATIO_LOOKUP",
"dependencies": {
"connections": [
{
"id": "HELLO_WORLD1",
"lockedFlag": false,
"name": "Hello World1",
"role": "SOURCE",
"status": "CONFIGURED",
"type": "rest",
"usage": 6
}
],
"lookups": [
{
"lockedFlag": false,
"name": "COMMON_LOOKUP_VARIABLES",
"status": "CONFIGURED",
"usage": 1
}
]
},
"description": "",
"eventSubscriptionFlag": false,
"filmstrip": [
{
"code": "HELLO_WORLD1",
"iconUrl": "/images/rest/rest_icon_46.png",
"name": "Hello World1",
"role": "SOURCE",
"status": "CONFIGURED"
}
],
"id": "HELLO_INTEGRATIO_LOOKUP|01.00.0000",
"lockedFlag": false,
"name": "HELLO_INTEGRATION_LOOKUP",
"pattern": "Orchestration",
"patternDescription": "Map Data",
"payloadTracingEnabledFlag": true,
"publishFlag": false,
"scheduleApplicable": false,
"scheduleDefined": false,
"status": "ACTIVATED",
"style": "FREEFORM",
"styleDescription": "Orchestration",
"tempCopyExists": false,
"tracingEnabledFlag": true,
"version": "01.00.0000",
"warningMsg": "ACTIVATE_PUBLISH_NO_CONN"
},
{
"code": "HI_INTEGRATION",
"dependencies": {
"connections": [
{
"id": "HELLO_WORLD1",
"lockedFlag": false,
"name": "Hello World1",
"role": "SOURCE",
"status": "CONFIGURED",
"type": "rest",
"usage": 6
}
]
},
"description": "",
"eventSubscriptionFlag": false,
"filmstrip": [
{
"code": "HELLO_WORLD1",
"iconUrl": "/images/rest/rest_icon_46.png",
"name": "Hello World1",
"role": "SOURCE",
"status": "CONFIGURED"
}
],
"id": "HI_INTEGRATION|01.00.0000",
"lockedFlag": false,
"name": "HI_INTEGRATION",
"pattern": "Orchestration",
"patternDescription": "Map Data",
"payloadTracingEnabledFlag": true,
"publishFlag": false,
"scheduleApplicable": false,
"scheduleDefined": false,
"status": "ACTIVATED",
"style": "FREEFORM",
"styleDescription": "Orchestration",
"tempCopyExists": false,
"tracingEnabledFlag": true,
"version": "01.00.0000",
"warningMsg": "ACTIVATE_PUBLISH_NO_CONN"
}
],
"isCloneAllowed": false,
"isViewAllowed": false,
"name": "SAMPLE_PACKAGE",
"type": "DEVELOPED"
}
The problem is that the lookups key is not always present so, you cannot use the [] on it. So, instead you can use the map function and provide a default before piping to the map function like below
[
{ id: .id },
{
integrations: [
.integrations[]|{
id: .id,
code: .code,
dependencies: {
connections: (.dependencies.connections//[]|map({id,status}))[0],
lookups: (.dependencies.lookups//[]|map({name,status}))[0]
}
}
]
}
]
The (.dependencies.lookups//[]|map({name,status}))[0] has the effect of passing an empty array to the map function which results in a null value when accessing the first element.
See in action https://jqplay.org/s/zQBkHtnzOd1
The provided JQ statement works fine for single elements in the array , but incase the array contains multiple elements it only fetches the first element. Also i updated the dependencies object to capture all the arrays ( connections,lookups,certificates,libraries,integrations)
Below is the modified one. Please suggest for any better options.
[
{ id: .id },
{
integrations: [
.integrations[]|{
id: .id,
code: .code,
dependencies: {
connections: (.dependencies.connections//[]|map({id,status})),
lookups: (.dependencies.lookups//[]|map({name,status})),
certificates: (.dependencies.certificates//[]|map({id,status})),
libraries: (.dependencies.libraries//[]|map({code,status,version})),
integrations: (.dependencies.integrations//[]|map({code,version}))
}
}
]
}
]|del(..|select(.==[]))
Note: To remove the empty arrays del function is added which is giving the below output :
[
{
"id": "SAMPLE_PACKAGE"
},
{
"integrations": [
{
"id": "HELLO_INTEGRATION|01.00.0000",
"code": "HELLO_INTEGRATION",
"dependencies": {
"connections": [
{
"id": "HELLO_WORLD1",
"status": "CONFIGURED"
},
{
"id": "HELLO_WORLD2",
"status": "CONFIGURED"
}
]
}
},
{
"id": "HELLO_INTEGRATIO_LOOKUP|01.00.0000",
"code": "HELLO_INTEGRATIO_LOOKUP",
"dependencies": {
"connections": [
{
"id": "HELLO_WORLD1",
"status": "CONFIGURED"
}
],
"lookups": [
{
"name": "COMMON_LOOKUP_VARIABLES",
"status": "CONFIGURED"
}
]
}
},
{
"id": "HI_INTEGRATION|01.00.0000",
"code": "HI_INTEGRATION",
"dependencies": {
"connections": [
{
"id": "HELLO_WORLD1",
"status": "CONFIGURED"
}
]
}
}
]
}
]
I'm working on a sync server that keeps the Office 365 events and my calendering app in sync
I subscribed to a push notification for user's event calendar that has the following custom single extended property.
Sample subscription request payload
{
"resource": "/me/events?$expand=singleValueExtendedProperties($filter=id%20eq%20'\''String%20{66f5a359-4659-4830-9070-00047ec6ac6e}%20Name%20CUSTOM'\'')",
"notificationUrl": "https://serverurl.xxxx.com/dev/notification",
"changeType": "updated,created",
"clientState": "123456-fad3-4191-9a66-123456789",
"expirationDateTime": "2018-03-17T11:00:00.0000000Z"
}
Then I do a single update of calendar event that has the above custom single extended property. On update, the sync server receives multiple notifications (2-3 notifications) for just updating the title of the event.
Notification 1:
{
"value": [{
"subscriptionId": "9645fed8-dc53-4955-b3a1-2d2b9ac5728f",
"subscriptionExpirationDateTime": "2018-03-17T11:00:00+00:00",
"changeType": "updated",
"resource": "<masked>",
"resourceData": {
"#odata.type": "#Microsoft.Graph.Event",
"#odata.id": "<masked>",
"#odata.etag": "W/\"+JK7q7qG1U+aBgDQ2ypjIQAAVnP6yQ==\"",
"id": "AAMkAGJmZjA5NzI0LWM5NTgtNGRhYy04MDExLTJmZTY4ZTJkNmVlYQBGAAAAAAC-F40EZzuzSqgA9N8VQW0zBwD4kruruobVT5oGANDbKmMhAAAAAAENAAD4kruruobVT5oGANDbKmMhAABV-OaMAAA=",
"createdDateTime": "2018-03-13T13:30:54.740501Z",
"lastModifiedDateTime": "2018-03-13T13:42:33.7107864Z",
"changeKey": "+JK7q7qG1U+aBgDQ2ypjIQAAVnP6yQ==",
"categories": [],
"originalStartTimeZone": "Pacific Standard Time",
"originalEndTimeZone": "Pacific Standard Time",
"iCalUId": "040000008200E00074C5B7101A82E0080000000006474883CFBAD30100000000000000001000000021D57F3032480543BE96AE56D8816FDF",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Microsoft DEMO - 2 UPDATED",
"bodyPreview": "Let's get together!",
"importance": "Normal",
"sensitivity": "Normal",
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "Busy",
"type": "SingleInstance",
"webLink": "<masked>",
"onlineMeetingUrl": null,
"responseStatus": {
"Response": "Organizer",
"Time": "0001-01-01T00:00:00Z"
},
"body": {
"ContentType": "HTML",
"Content": "<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta content=\"text/html; charset=us-ascii\">\r\n</head>\r\n<body>\r\nLet's get together!\r\n</body>\r\n</html>\r\n"
},
"start": {
"DateTime": "2018-03-29T01:00:00Z",
"TimeZone": "tzone://Microsoft/Utc"
},
"end": {
"DateTime": "2018-03-29T06:00:00Z",
"TimeZone": "tzone://Microsoft/Utc"
},
"location": {
"DisplayName": "",
"LocationType": "Default",
"UniqueIdType": "Unknown",
"Address": {
"Type": "Unknown"
},
"Coordinates": {}
},
"locations": [],
"recurrence": null,
"attendees": [{
"Type": "Required",
"Status": {
"Response": "None",
"Time": "0001-01-01T00:00:00Z"
},
"EmailAddress": {
"Name": "<masked>",
"Address": "<masked>"
}
}],
"organizer": {
"EmailAddress": {
"Name": "<masked>",
"Address": "<masked>"
}
}
},
"clientState": "123456-fad3-4191-9a66-123456789"
}]
}
Notification 2:
{
"value": [{
"subscriptionId": "9645fed8-dc53-4955-b3a1-2d2b9ac5728f",
"subscriptionExpirationDateTime": "2018-03-17T11:00:00+00:00",
"changeType": "updated",
"resource": "<masked>",
"resourceData": {
"#odata.type": "#Microsoft.Graph.Event",
"#odata.id": "<masked>",
"#odata.etag": "W/\"+JK7q7qG1U+aBgDQ2ypjIQAAVnP6yw==\"",
"id": "AAMkAGJmZjA5NzI0LWM5NTgtNGRhYy04MDExLTJmZTY4ZTJkNmVlYQBGAAAAAAC-F40EZzuzSqgA9N8VQW0zBwD4kruruobVT5oGANDbKmMhAAAAAAENAAD4kruruobVT5oGANDbKmMhAABV-OaMAAA=",
"createdDateTime": "2018-03-13T13:30:54.740501Z",
"lastModifiedDateTime": "2018-03-13T13:42:33.869926Z",
"changeKey": "+JK7q7qG1U+aBgDQ2ypjIQAAVnP6yw==",
"categories": [],
"originalStartTimeZone": "Pacific Standard Time",
"originalEndTimeZone": "Pacific Standard Time",
"iCalUId": "<masked>",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Microsoft DEMO - 2 UPDATED",
"bodyPreview": "Let's get together!",
"importance": "Normal",
"sensitivity": "Normal",
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "Busy",
"type": "SingleInstance",
"webLink": "<masked>",
"onlineMeetingUrl": null,
"responseStatus": {
"Response": "Organizer",
"Time": "0001-01-01T00:00:00Z"
},
"body": {
"ContentType": "HTML",
"Content": "<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta content=\"text/html; charset=us-ascii\">\r\n</head>\r\n<body>\r\nLet's get together!\r\n</body>\r\n</html>\r\n"
},
"start": {
"DateTime": "2018-03-29T01:00:00Z",
"TimeZone": "tzone://Microsoft/Utc"
},
"end": {
"DateTime": "2018-03-29T06:00:00Z",
"TimeZone": "tzone://Microsoft/Utc"
},
"location": {
"DisplayName": "",
"LocationType": "Default",
"UniqueIdType": "Unknown",
"Address": {
"Type": "Unknown"
},
"Coordinates": {}
},
"locations": [],
"recurrence": null,
"attendees": [{
"Type": "Required",
"Status": {
"Response": "None",
"Time": "0001-01-01T00:00:00Z"
},
"EmailAddress": {
"Name": "<masked>",
"Address": "<masked>"
}
}],
"organizer": {
"EmailAddress": {
"Name": "<masked>",
"Address": "<masked>"
}
}
},
"clientState": "123456-fad3-4191-9a66-123456789"
}]
}
Notification 3:
{
"value": [{
"subscriptionId": "9645fed8-dc53-4955-b3a1-2d2b9ac5728f",
"subscriptionExpirationDateTime": "2018-03-17T11:00:00+00:00",
"changeType": "updated",
"resource": "<masked>",
"resourceData": {
"#odata.type": "#Microsoft.Graph.Event",
"#odata.id": "<masked>",
"#odata.etag": "W/\"+JK7q7qG1U+aBgDQ2ypjIQAAVnP6yw==\"",
"id": "AAMkAGJmZjA5NzI0LWM5NTgtNGRhYy04MDExLTJmZTY4ZTJkNmVlYQBGAAAAAAC-F40EZzuzSqgA9N8VQW0zBwD4kruruobVT5oGANDbKmMhAAAAAAENAAD4kruruobVT5oGANDbKmMhAABV-OaMAAA=",
"createdDateTime": "2018-03-13T13:30:54.740501Z",
"lastModifiedDateTime": "2018-03-13T13:42:33.869926Z",
"changeKey": "+JK7q7qG1U+aBgDQ2ypjIQAAVnP6yw==",
"categories": [],
"originalStartTimeZone": "Pacific Standard Time",
"originalEndTimeZone": "Pacific Standard Time",
"iCalUId": "<masked>",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Microsoft DEMO - 2 UPDATED",
"bodyPreview": "Let's get together!",
"importance": "Normal",
"sensitivity": "Normal",
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "Busy",
"type": "SingleInstance",
"webLink": "<masked>",
"onlineMeetingUrl": null,
"responseStatus": {
"Response": "Organizer",
"Time": "0001-01-01T00:00:00Z"
},
"body": {
"ContentType": "HTML",
"Content": "<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n<meta content=\"text/html; charset=us-ascii\">\r\n</head>\r\n<body>\r\nLet's get together!\r\n</body>\r\n</html>\r\n"
},
"start": {
"DateTime": "2018-03-29T01:00:00Z",
"TimeZone": "tzone://Microsoft/Utc"
},
"end": {
"DateTime": "2018-03-29T06:00:00Z",
"TimeZone": "tzone://Microsoft/Utc"
},
"location": {
"DisplayName": "",
"LocationType": "Default",
"UniqueIdType": "Unknown",
"Address": {
"Type": "Unknown"
},
"Coordinates": {}
},
"locations": [],
"recurrence": null,
"attendees": [{
"Type": "Required",
"Status": {
"Response": "None",
"Time": "0001-01-01T00:00:00Z"
},
"EmailAddress": {
"Name": "<masked>",
"Address": "<masked>"
}
}],
"organizer": {
"EmailAddress": {
"Name": "<masked>",
"Address": "<masked>"
}
}
},
"clientState": "123456-fad3-4191-9a66-123456789"
}]
}
I expected just one notification for every update (In my case I just did an update on event title), but the server is receiving multiple notifications with just #odata.etag different in the notifications. Is this expected?
When making a change to any item, the server may need to perform several modifications on the item, as well as other related items behind the scenes. Each of these modifications would result in a notification. There also could be other entities that are listening to changes, and reacting to them, potentially causing further changes and hence more notifications on the item. So in short, there is no guarantee regarding the number of notifications that you may receive as a result of a single API call. That is specially true for high-level calendaring operations, which often involve complex workflows on the server.
In this case you can see that in fact you have received three different change keys, indicating that the item has been modified multiple times.
I created a task that talks to a REST API to retreive the values for 2 picklists.
Filling the first dropdown box works fine, when using just the jsonpath.
Based on the first picklist I'd like to retreive values of the second list.
I've tried some variations and I'm trying something like this:
The json which I receive in the first rest call is similar to:
{
"id": "45",
"href": "https://selfservice/api/configurations/45/",
"name": "Type",
"description": "",
"version": "0.0.4",
"attributes": [
{
"value": {
"sdk-object": {
"type": "ConfigurationElement",
"id": "56"
}
},
"type": "ConfigurationElement",
"name": "win"
},
{
"value": {
"sdk-object": {
"type": "ConfigurationElement",
"id": "57"
}
},
"type": "ConfigurationElement",
"name": "lin"
}
]
}
I try to show the attributes name in the list and need the id of the attribute in the second picklist.
I created the following datasourcebindings in the task.json. Of course, the targets exist in the task.
task.json:
{
"id": "GUID",
"name": "Spinup",
"friendlyName": "Create environment",
"description": "Starts Workflow to create an environment. ___ The following placeholders are created deplending on the template and can be used in the rest of the release:**XLDEnvironment** and **testAgentHostname**",
"category": "Deploy",
"author": "***",
"version": {
"Major": 0,
"Minor": 0,
"Patch": 33
},
"minimumAgentVersion": "1.95.3",
"inputs": [
{
"label": "Endpoint",
"name": "connectedServiceName",
"required": true,
"type": "connectedService:server",
"helpMarkDown": "endpoint to connect to."
},
{
"name": "stage",
"type": "string",
"label": "Stage",
"defaultValue": "$(Release.EnvironmentName)",
"required": true,
"helpMarkDown": "Stage of the release, default value is based on the pipeline."
},
{
"name": "releaseName",
"type": "string",
"label": "Environment name",
"defaultValue": "$(Release.ReleaseName)",
"required": true,
"helpMarkDown": "Name of the environment that will be created."
},
{
"name": "owner",
"type": "string",
"label": "Owner of the environment",
"defaultValue": "***",
"required": true,
"helpMarkDown": "It is common to use the initials of the product owner in this field. There has to be a valid AD user owner of each environment. This can also be set by using a variable through the pipeline."
},
{
"name": "group",
"type": "string",
"label": "Group of the owner",
"defaultValue": "",
"required": true,
"helpMarkDown": "group that owns the environment. groups can be requested by the infrastructure department. Example: ****"
},
{
"name": "platform",
"type": "pickList",
"label": "Platform (OS)",
"defaultValue": "",
"required": true,
"helpMarkDown": "Choose the type of the target platform."
},
{
"name": "size",
"type": "pickList",
"label": "Environment Template",
"defaultValue": "",
"required": true,
"helpMarkDown": "Size of the environment to create."
}
],
"dataSourceBindings": [
{
"dataSourceName": "GetCEPlatformType",
"endpointId": "$(connectedServiceName)",
"target": "platform",
"selector": "jsonpath:$.attributes[*].name",
"keySelector": "jsonpath:$.attributes[*].value.sdk-object.id"
},
{
"dataSourceName": "GetCEPlatformSize",
"endpointId": "$(connectedServiceName)",
"target": "size",
"parameters": {
"platformTypeId": "$(platform)"
}
}
],
"instanceNameFormat": "Spin up $(size) $(platform) environment",
"execution": {
"PowerShell3": {
"target": "$(currentDirectory)\\task.ps1",
"argumentFormat": "",
"workingDirectory": "$(currentDirectory)"
}
}
}
vss-extension.json:
{
"manifestVersion": 1,
"id": "*****",
"name": "Release Tasks",
"version": "1.0.1",
"publisher": "***",
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"description": "Tools to contact ***. Includes a task to spin up a platform and a task to remove the platform.",
"categories": [
"Build and release"
],
"icons": {
"default": "images/extension-icon.png"
},
"files": [
{
"path": "RemoveEnvironment"
},
{
"path": "SpinUpEnvironment"
}
],
"contributions": [
{
"id": "******",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "RemoveEnvironment"
}
},
{
"id": "*********",
"type": "ms.vss-distributed-task.task",
"targets": [
"ms.vss-distributed-task.tasks"
],
"properties": {
"name": "SpinUpEnvironment"
}
},
{
"description": "Service Endpoint type for all connections",
"id": "endpoint-type",
"properties": {
"authenticationSchemes": [
{
"inputDescriptors": [
{
"description": "Username",
"id": "username",
"inputMode": "textbox",
"name": "Username",
"validation": {
"dataType": "string",
"isRequired": true
}
},
{
"description": "Password",
"id": "password",
"inputMode": "passwordbox",
"isConfidential": true,
"name": "Password",
"validation": {
"dataType": "string",
"isRequired": false
}
}
],
"type": "ms.vss-endpoint.endpoint-auth-scheme-basic"
}
],
"dataSources": [
{
"endpointUrl": "api/configurations/*****/",
"name": "GetCEPlatformType",
"resultSelector": "jsonpath:$.attributes[*].name"
},
{
"endpointUrl": "api/configurations/$(platformTypeId)/",
"name": "GetCEPlatformSize",
"resultSelector": "jsonpath:$.attributes[*].name"
}
],
"displayName": "*****",
"helpMarkDown": "Enter the url and credentials to connect to the endpoint.",
"name": "server",
"url": {
"displayName": "Server URL",
"helpText": "Url for the server to connect to."
}
},
"targets": [
"ms.vss-endpoint.endpoint-types"
],
"type": "ms.vss-endpoint.service-endpoint-type"
}
]
}
Sadly I can't get this to work. The datasources exist in the endpoint, but I'm not sure what to do with the resultSelector.
Does anyone have an idea on how to get this to work? The documentation on this isn't too good.
I'm not familiar with mustache, but in the mustache test tool this seems to work.
Thoughts are appreciated!
Try with this in the first data source:
{
"dataSourceName": "dsList1",
"endpointId": "$(connectedServiceName)",
"target": "list1",
"selector": "jsonpath:$.attributes[*].name",
"keySelector": "jsonpath:$.attributes[*].value.sdk-object.id"
}
Update:
You were trying to use "platformTypeId" in vss-extension.json file while it was defined in task.json, this cause the error message you mentioned in the comment.
By the way, I just noticed that you are using "dataSourceBindings", then you cannot use "selector" and "KeySelector" to parse the result since they are used for "sourceDefinitions".
To achieve the feature you want with "dataSourceBindings", you can definition the endpoint url in the task.json directly instead of defining datasource in endpoint contribution.
So you can move the datasources section in the vss-extension.json file first, and then in the task.json file, change to following:
"dataSourceBindings": [
{
"endpointId": "$(connectedServiceName)",
"endpointURL": "api/configurations/*****/",
"target": "platform",
"resultselector": "jsonpath:$.attributes[*]",
"resultTemplate": "{ \"Value\" : \"{{{value.id}}}\", \"DisplayValue\" : \"{{{name}}}\" }"
},
{
"endpointId": "$(connectedServiceName)",
"endpointURL": "api/configurations/$(platformTypeId)/",
"target": "size"
}
],
I am using Vimeo API, while making a get call to access a user's video I am doing
https://api.vimeo.com/users/61402929/videos?access_token=token
this is returning a json response
{
"total": 1,
"page": 1,
"per_page": 25,
"paging": {
"next": null,
"previous": null,
"first": "/users/61402929/videos?access_token=365879aad6244864dab70902890fc1a1&page=1",
"last": "/users/61402929/videos?access_token=365879aad6244864dab70902890fc1a1&page=1"
},
"data": [
{
"uri": "/videos/200383630",
"name": "Bhuvan bam _ Bb ki vines _ playing piano _ Saagar jaisi aankhon waali _ bhuvan bam live (360p_30fps_H264-96kbit_AAC)",
"description": "BB Ki Vines",
"link": "https://vimeo.com/200383630",
"duration": 59,
"width": 320,
"language": null,
"height": 320,
"embed": {
"uri": null,
"html": "<iframe src=\"https://player.vimeo.com/video/200383630?badge=0&autopause=0&player_id=0\" width=\"320\" height=\"320\" frameborder=\"0\" title=\"Bhuvan bam _ Bb ki vines _ playing piano _ Saagar jaisi aankhon waali _ bhuvan bam live (360p_30fps_H264-96kbit_AAC)\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>",
"buttons": {
"like": true,
"watchlater": true,
"share": true,
"embed": true,
"hd": false,
"fullscreen": true,
"scaling": true
},
"logos": {
"vimeo": true,
"custom": {
"active": false,
"link": null,
"sticky": false
}
},
"title": {
"name": "user",
"owner": "user",
"portrait": "user"
},
"playbar": true,
"volume": true,
"color": "00adef"
},
"created_time": "2017-01-20T17:57:04+00:00",
"modified_time": "2017-01-20T17:58:41+00:00",
"release_time": "2017-01-20T17:57:04+00:00",
"content_rating": [
"unrated"
],
"license": null,
"privacy": {
"view": "anybody",
"embed": "public",
"download": true,
"add": true,
"comments": "anybody"
},
"pictures": {
"uri": "/videos/200383630/pictures/613872508",
"active": true,
"type": "custom",
"sizes": [
{
"width": 100,
"height": 75,
"link": "https://i.vimeocdn.com/video/613872508_100x75.webp?r=pad",
"link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F613872508_100x75.webp&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
},
{
"width": 200,
"height": 150,
"link": "https://i.vimeocdn.com/video/613872508_200x150.webp?r=pad",
"link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F613872508_200x150.webp&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
},
{
"width": 295,
"height": 166,
"link": "https://i.vimeocdn.com/video/613872508_295x166.webp?r=pad",
"link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F613872508_295x166.webp&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
},
{
"width": 640,
"height": 640,
"link": "https://i.vimeocdn.com/video/613872508_640x640.webp?r=pad",
"link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F613872508_640x640.webp&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
},
{
"width": 960,
"height": 960,
"link": "https://i.vimeocdn.com/video/613872508_960x960.webp?r=pad",
"link_with_play_button": "https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F613872508_960x960.webp&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png"
}
],
"resource_key": "fdb74e1e2dcaf7c929cfe14240765f45f2d2a302"
},
"tags": [],
"stats": {
"plays": 0
},
"metadata": {
"connections": {
"comments": {
"uri": "/videos/200383630/comments",
"options": [
"GET",
"POST"
],
"total": 0
},
"credits": {
"uri": "/videos/200383630/credits",
"options": [
"GET",
"POST"
],
"total": 1
},
"likes": {
"uri": "/videos/200383630/likes",
"options": [
"GET"
],
"total": 0
},
"pictures": {
"uri": "/videos/200383630/pictures",
"options": [
"GET",
"POST"
],
"total": 1
},
"texttracks": {
"uri": "/videos/200383630/texttracks",
"options": [
"GET",
"POST"
],
"total": 0
},
"related": null
},
"interactions": {
"watchlater": {
"added": false,
"added_time": null,
"uri": "/users/61402929/watchlater/200383630"
}
}
},
"user": {
"uri": "/users/61402929",
"name": "Rishabh Kumar",
"link": "https://vimeo.com/user61402929",
"location": null,
"bio": null,
"created_time": "2017-01-11T16:15:43+00:00",
"account": "basic",
"pictures": null,
"websites": [],
"metadata": {
"connections": {
"activities": {
"uri": "/users/61402929/activities",
"options": [
"GET"
]
},
"albums": {
"uri": "/users/61402929/albums",
"options": [
"GET"
],
"total": 0
},
"appearances": {
"uri": "/users/61402929/appearances",
"options": [
"GET"
],
"total": 0
},
"categories": {
"uri": "/users/61402929/categories",
"options": [
"GET"
],
"total": 0
},
"channels": {
"uri": "/users/61402929/channels",
"options": [
"GET"
],
"total": 0
},
"feed": {
"uri": "/users/61402929/feed",
"options": [
"GET"
]
},
"followers": {
"uri": "/users/61402929/followers",
"options": [
"GET"
],
"total": 0
},
"following": {
"uri": "/users/61402929/following",
"options": [
"GET"
],
"total": 0
},
"groups": {
"uri": "/users/61402929/groups",
"options": [
"GET"
],
"total": 0
},
"likes": {
"uri": "/users/61402929/likes",
"options": [
"GET"
],
"total": 0
},
"moderated_channels": {
"uri": "/users/61402929/channels?filter=moderated",
"options": [
"GET"
],
"total": 0
},
"portfolios": {
"uri": "/users/61402929/portfolios",
"options": [
"GET"
],
"total": 0
},
"videos": {
"uri": "/users/61402929/videos",
"options": [
"GET"
],
"total": 1
},
"watchlater": {
"uri": "/users/61402929/watchlater",
"options": [
"GET"
],
"total": 0
},
"shared": {
"uri": "/users/61402929/shared/videos",
"options": [
"GET"
],
"total": 0
},
"pictures": {
"uri": "/users/61402929/pictures",
"options": [
"GET",
"POST"
],
"total": 0
},
"watched_videos": {
"uri": "/me/watched/videos",
"options": [
"GET"
],
"total": 0
}
}
},
"preferences": {
"videos": {
"privacy": "anybody"
}
},
"content_filter": [
"language",
"drugs",
"violence",
"nudity",
"safe",
"unrated"
],
"resource_key": "6fe192b4cb782d1341fbf3fb3d0ba04a0295236d"
},
"app": null,
"status": "available",
"resource_key": "cad1f2b7d388491329363a4936f0219fa4dfd18b",
"embed_presets": null
}
]
}
however I am only interested in fields paging, total, and some fields of data array therefore i am using filter as below
https://api.vimeo.com/users/61402929/videos?access_token=token&fields=paging,data.name,data.description,data.link,data.pictures.sizes.link
but the response of above call is
{
"total": 1,
"page": 1,
"per_page": 25,
"paging": {
"next": null,
"previous": null,
"first": "/users/61402929/videos?access_token=365879********0902890fc1a1&fields=paging%2Cdata.name%2Cdata.description%2Cdata.link%2Cdata.pictures.sizes.link&page=1",
"last": "/users/61402929/videos?access_token=365879********0902890fc1a1&fields=paging%2Cdata.name%2Cdata.description%2Cdata.link%2Cdata.pictures.sizes.link&page=1"
},
"data": [
[]
]
}
Edit: Also the response for the call
https://api.vimeo.com/users/61402929/videos?access_token=token&fields=paging
is
{
"total": 1,
"page": 1,
"per_page": 25,
"paging": {
"next": null,
"previous": null,
"first": "/users/61402929/videos?access_token=365879*********70902890fc1a1&fields=paging&page=1",
"last": "/users/61402929/videos?access_token=365879*********70902890fc1a1&fields=paging&page=1"
},
"data": [
[]
]
}
I am unable to figure out why the request is not being processed correctly.
A couple of things: First, the access token should be passed in the auth header of the request, not in the request uri as you mentioned: https://developer.vimeo.com/api/authentication#making-requests
With regards to the fields filter, the filter only applies to the keys nested under data. The paging array is always returned for requests where multiple items are returned.
So your example request should look like this:
https://api.vimeo.com/users/61402929/videos?fields=name,description,link,pictures.sizes.link
More info here: https://developer.vimeo.com/api/spec#json-filter
Hope this helps!
This is not a direct answer to this question, but in case anyone else like me ends up finding this page through search results, I have wasted a couple of hours of my life with a similar problem, wondering why the results returned by Vimeo's API were seemingly completely erratic, when dialing up the API using Laravel with this package like so:
$response = Vimeo::request('/me/albums/xxxxxxx/videos?fields=name,uri,duration,width,height,link', `['per_page' => 100], 'GET');`
After a lot of trial and error I discovered that it always seemed to miss the last field listed in the query parameter.
Anyway, the solution was to always send the request with a trailing comma! i.e.
$response = Vimeo::request('/me/albums/xxxxxxx/videos?fields=name,uri,duration,width,height,link,', `['per_page' => 100], 'GET');`
Is this an absolutely face-palmingly ridiculous requirement? Why, yes. Yes it is. But there you have it.