not able to parse the ansible output - ansible

I am not able to parse ansible folwing output. trying to get the ip address.
I am trying to get ip address of azure vm, to get the ip. I am using the azure_rm_networkinterface_facts module, in this module I am feeding the nic name, which stored in used the diet.
Here is my output, which i want to parse.
ok: [
localhost
]=>(item={
'value': [
u'datamover-nic10'
],
'key': u'data-mover'
})=>{
"ansible_facts": {
"azure_networkinterfaces": [
{
"etag": "W/\"08842209-be15-1144f26\"",
"id": "/subscriptions/1cf78a5c-5a30--c52c2d3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/networkInterfaces/datamover-nic10",
"location": "westus",
"name": "datamover-nic10",
"properties": {
"dnsSettings": {
"appliedDnsServers": [
],
"dnsServers": [
],
"internalDomainNameSuffix": "3endvnfzb.dx.internal.cloudapp.net"
},
"enableAcceleratedNetworking": false,
"enableIPForwarding": false,
"ipConfigurations": [
{
"etag": "W/\"088421144f26\"",
"id": "/subscriptions/1cf78a52c2d3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/networkInterfaces/datamover-nic10/ipConfigurations/ip1",
"name": "ip1",
"properties": {
"primary": true,
"privateIPAddress": "10.172.240.11",
"privateIPAddressVersion": "IPv4",
"privateIPAllocationMethod": "Static",
"provisioningState": "Succeeded",
"subnet": {
"id": "/subscriptions/1cf78a5c-5ac2d3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/virtualNetworks/vNetOne/subnets/vmsubnet"
}
}
}
],
"macAddress": "00-0D-3A-36-B3-5C",
"networkSecurityGroup": {
"id": "/subscriptions/1cf78ad3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/networkSecurityGroups/datamover-nsg"
},
"primary": true,
"provisioningState": "Succeeded",
"resourceGuid": "03114",
"virtualMachine": {
"id": "/subscriptions/1cf7d3d21b6/resourceGroups/DEVT/providers/Microsoft.Compute/virtualMachines/datamover"
}
},
"tags": {
"component": "datamover",
"provider": "B50E5F"
},
"type": "Microsoft.Network/networkInterfaces"
}
]
},
"changed": false,
"item": {
"key": "data-mover",
"value": [
"datamover-nic10"
]
}
}ok: [
localhost
]=>(item={
'value': [
u'database-nic00'
],
'key': u'database'
})=>{
"ansible_facts": {
"azure_networkinterfaces": [
{
"etag": "W/\"60bfd8c17323612\"",
"id": "/subscriptions/1cf72d3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/networkInterfaces/database-nic00",
"location": "westus",
"name": "database-nic00",
"properties": {
"dnsSettings": {
"appliedDnsServers": [
],
"dnsServers": [
],
"internalDomainNameSuffix": "3wjfzb.dx.internal.cloudapp.net"
},
"enableAcceleratedNetworking": false,
"enableIPForwarding": false,
"ipConfigurations": [
{
"etag": "W/\"603612\"",
"id": "/subscriptions/1c2d3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/networkInterfaces/database-nic00/ipConfigurations/ip1",
"name": "ip1",
"properties": {
"primary": true,
"privateIPAddress": "10.172.240.4",
"privateIPAddressVersion": "IPv4",
"privateIPAllocationMethod": "Static",
"provisioningState": "Succeeded",
"subnet": {
"id": "/subscriptions/1c3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/virtualNetworks/vNetOne/subnets/vmsubnet"
}
}
},
{
"etag": "W/\"60b3612\"",
"id": "/subscriptions/1cfd3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/networkInterfaces/database-nic00/ipConfigurations/ip2",
"name": "ip2",
"properties": {
"primary": false,
"privateIPAddress": "10.172.0.6",
"privateIPAddressVersion": "IPv4",
"privateIPAllocationMethod": "Static",
"provisioningState": "Succeeded",
"subnet": {
"id": "/subscriptions/1d3d21b6/resourceGroups/DEVT/providers/Microsoft.Network/virtualNetworks/vNetOne/subnets/vmsubnet"
}
}
}
],
"macAddress": "00-0D-3A-36-BC-FB",
"networkSecurityGroup": {
"id": "/subscriptions/1cf52c2d3d21b6/resourceGroups/ImcSite-UPAASDEVT/providers/Microsoft.Network/networkSecurityGroups/database-nsg"
},
"primary": true,
"provisioningState": "Succeeded",
"resourceGuid": "4d2fd4441e3c",
"virtualMachine": {
"id": "/subscriptions/1cf7d3d21b6/resourceGroups/DEVT/providers/Microsoft.Compute/virtualMachines/database-vm0"
}
},
"tags": {
"component": "database",
"provider": "B52B9A0E5F"
},
"type": "Microsoft.Network/networkInterfaces"
}
]
},
"changed": false,
"item": {
"key": "database",
"value": [
"database-nic00"
]
}
}
I am trying to parse and get 10.172.240.11 and 10.172.240.4 address from the output using the following method. Can you please someone help me on this?
- debug: msg=" {{ item.value[0] }}"
with_dict:
- "{{ vm_net_intf }}"
I expect to print 10.172.240.11 and 10.172.240.4 ip address in debug

With the last part of the ansible_facts the play below below
tasks:
- debug:
msg: "{{ item.properties.ipConfigurations|
json_query('[].properties.privateIPAddress') }}"
loop: "{{ ansible_facts.azure_networkinterfaces }}"
gives (abridged):
"msg": [
"10.172.240.4",
"10.172.0.6"
]

Related

Ansible - Create JSON output by merging facts

I am trying to create a JSON output from an Ansible playbook that will be sent to a 3rd party system via file or RabbitMQ. The issue I am having is creating the JSON file/body to send as output.
Environment:
Ansible: 2.10.17
JSON input file: 'Cannot change the format of the input file'
Logical process:
Receive a JSON input file => working
Convert JSON input file to a fact (JSON_input) => working
Search through the a directory and find any folder (bucket) not already
listed (var_client_buckets_diff_state_current)=> working
Create new fact which consist of [input file + var_client_buckets_diff_state_current] (create json file structure for new fact) => not
working
Send the new fact to 3rd party => not attempted yet
What has been attempted:
Tried to use the 'update_fact' with indicies => this seemed not to
work and was intended for updating an existing variable within the
fact
Tried to use the 'set_fact' + [item] => not what I expected
Input_file:
{
"siteIdentifier": "site1",
"configurations": [
{
"tenantName": "patcorp",
"keypairConfigurations": [
{
"accessKey": "key1",
"secretKey": "kjjhgghfdgf765ghdf",
"port": "60008",
"mountPath": "/tmp/mnt/scoutfs/patcorp",
"buckets": [
{
"bucketName": "bucket1",
"settings": {
"status": "OK"
}
},
{
"bucketName": "bucket2",
"settings": {
"status": "PENDING-DELETION"
}
}
]
}
]
},
{
"tenantName": "mattcorp",
"keypairConfigurations": [
{
"accessKey": "key3",
"secretKey": "jhgf785tkjjhg",
"port": "60010",
"mountPath": "/tmp/mnt/scoutfs/mattcorp",
"buckets": [
{
"bucketName": "bucket10",
"settings": {
"status": "OK"
}
},
{
"bucketName": "bucket11",
"settings": {
"status": "PENDING-DELETION"
}
}
]
}
]
}
]
}
Playbook:
---
- name: debug_playbook
hosts:
- localhost
gather_facts: true
vars:
var_client_buckets_diff_state_current: ['/tmp/mnt/scoutfs/mattcorp/bucket12', '/tmp/mnt/scoutfs/mattcorp/bucket22', '/tmp/mnt/scoutfs/patcorp/bucket07']
fact_json_updated: []
tasks:
## Find collections path via ansible.cfg
- name: debug_read_collections_path
ansible.builtin.debug:
msg: "{{ lookup('config', 'COLLECTIONS_PATHS') }}"
run_once: true
register: reg_debug_read_collections_path
## Read JSON file to create stdout
- name: cat_scoutam_client_master_assignments_raw
ansible.builtin.shell:
cmd: cat ./files/scoutam_client_master_assignments_2.json
run_once: true
delegate_to: localhost
register: reg_scoutam_client_master_assignments_raw
## Convert JSON input file into fact
- name: fact_scoutam_client_master_assignments
ansible.builtin.set_fact:
fact_scoutam_client_master_assignments: "{{ reg_scoutam_client_master_assignments_raw.stdout | from_json }}"
run_once: true
delegate_to: localhost
# - name: debug_scoutam_client_tenant_ids
# debug:
# msg: "{{ fact_scoutam_client_master_assignments | json_query(jmesquery) }}"
# vars:
# jmesquery: 'configurations[*].tenantName'
# run_once: true
# delegate_to: localhost
# register: reg_debug_scoutam_client_tenant_ids
## Create duplicate fact file with only diffs found from 'var_client_buckets_diff_state_current'
- name: create json file structure for new fact
ansible.builtin.set_fact:
fact_json_new:
siteIdentifier:
configurations:
- {tenantName: "{{ var_tenantName }}", keypairConfigurations: [{accessKey: , secretKey: , port: , mountPath: , buckets: [{bucketName: "{{ var_bucketName }}", settings: {status: }}] }]}
vars:
var_tenantName: "{{ item.split('/')[4] }}" ## take 'item' and find tenant name
var_bucketName: "{{ item.split('/')[5] }}" ## take 'item' and find bucket name
loop: "{{ var_client_buckets_diff_state_current }}" ## loop through buckets not within input file
register: reg_fact_json_new
## Create new JSON file (input file + any new buckets found )
- name: combine fact
ansible.builtin.set_fact:
fact_json_updated: "{{ fact_json_updated + item }}"
loop: "{{ reg_fact_json_new.results | json_query('[*].ansible_facts.fact_json_new') }}"
- name: debug fact - fact_json_updated
debug:
var: fact_json_updated
## End of playbook message
- name: "debug_playbook_{{ ansible_play_name }}_completion"
ansible.builtin.debug:
msg: "Playbook {{ playbook_dir }}/{{ ansible_play_name }} has finished."
...
Output from [create json file structure for new fact, combine fact]
TASK [combine fact] ************************************************************************************************************************************************************************************************************
task path: /app/ansible/ansible_linux_playbooks/playbooks/TEST_debug_facts_playbook/debug_playbook.yml:70
Thursday 28 October 2021 10:06:50 -0400 (0:00:00.078) 0:00:01.417 ******
ok: [localhost] => (item={'siteIdentifier': None, 'configurations': [{'tenantName': 'mattcorp', 'keypairConfigurations': [{'accessKey': None, 'secretKey': None, 'port': None, 'mountPath': None, 'buckets': [{'bucketName': 'bucket12', 'settings': {'status': None}}]}]}]}) => {
"ansible_facts": {
"fact_json_updated": [
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket12",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
}
]
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket12",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
}
}
ok: [localhost] => (item={'siteIdentifier': None, 'configurations': [{'tenantName': 'mattcorp', 'keypairConfigurations': [{'accessKey': None, 'secretKey': None, 'port': None, 'mountPath': None, 'buckets': [{'bucketName': 'bucket22', 'settings': {'status': None}}]}]}]}) => {
"ansible_facts": {
"fact_json_updated": [
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket12",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
},
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket22",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
}
]
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket22",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
}
}
ok: [localhost] => (item={'siteIdentifier': None, 'configurations': [{'tenantName': 'patcorp', 'keypairConfigurations': [{'accessKey': None, 'secretKey': None, 'port': None, 'mountPath': None, 'buckets': [{'bucketName': 'bucket07', 'settings': {'status': None}}]}]}]}) => {
"ansible_facts": {
"fact_json_updated": [
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket12",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
},
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket22",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
},
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket07",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "patcorp"
}
],
"siteIdentifier": null
}
]
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket07",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "patcorp"
}
],
"siteIdentifier": null
}
}
TASK [debug fact - reg_fact_json_updated] **************************************************************************************************************************************************************************************
task path: /app/ansible/ansible_linux_playbooks/playbooks/TEST_debug_facts_playbook/debug_playbook.yml:77
Thursday 28 October 2021 10:06:50 -0400 (0:00:00.100) 0:00:01.518 ******
ok: [localhost] => {
"fact_json_updated": [
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket12",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
},
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket22",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "mattcorp"
}
],
"siteIdentifier": null
},
{
"configurations": [
{
"keypairConfigurations": [
{
"accessKey": null,
"buckets": [
{
"bucketName": "bucket07",
"settings": {
"status": null
}
}
],
"mountPath": null,
"port": null,
"secretKey": null
}
],
"tenantName": "patcorp"
}
],
"siteIdentifier": null
}
]
}
Expected output JSON:
{
"siteIdentifier": "mas1-sos07",
"configurations": [
{
"tenantName": "patcorp",
"keypairConfigurations": [
{
"accessKey": "key1",
"secretKey": "kjjhgghfdgf765ghdf",
"port": "60008",
"mountPath": "/tmp/mnt/scoutfs/patcorp",
"buckets": [
{
"bucketName": "bucket1",
"settings": {
"status": "OK"
}
},
{
"bucketName": "bucket2",
"settings": {
"status": "PENDING-DELETION"
}
},
{
"bucketName": "bucket07",
"settings": {
"status": null
}
}
]
}
]
},
{
"tenantName": "mattcorp",
"keypairConfigurations": [
{
"accessKey": "key3",
"secretKey": "jhgf785tkjjhg",
"port": "60010",
"mountPath": "/tmp/mnt/scoutfs/mattcorp",
"buckets": [
{
"bucketName": "bucket10",
"settings": {
"status": "OK"
}
},
{
"bucketName": "bucket11",
"settings": {
"status": "PENDING-DELETION"
}
},
{
"bucketName": "bucket12",
"settings": {
"status": null
}
},
{
"bucketName": "bucket22",
"settings": {
"status": null
}
}
]
}
]
}
]
}

Move a key to a value into a list of dict in Ansible

I'm trying to transform keys of the items "datacenter_clusters" to a key/value pair in itself.
This will also to loop through the following list of dict :
"list_of_dict": [
{
"datacenter": "DC_A",
"datacenter_clusters": {
"CLUSTER_ALPHA": {
"datacenter": "DC_A",
"cluster_info_1": "xxxxxx",
"cluster_info_2": true,
"hosts": [
{
"folder": "/path/to/host-1",
"name": "hostname-1"
},
{
"folder": "/path/to/host-2",
"name": "hostname-2"
}
},
"CLUSTER_BETA": {
"datacenter": "DC_A",
"cluster_info_1": "yyyyyyy",
"cluster_info_2": false,
}
}
"vcenter": "vcenter-1"
},
{
"datacenter": "DC_B",
"datacenter_clusters": {
"CLUSTER_OMEGA": {
"datacenter": "DC_B",
"cluster_info_1": "aaaaaaaa",
"cluster_info_2": true,
},
"CLUSTER_ZETA": {
"datacenter": "DC_A",
"cluster_info_1": "bbbbbbbbbb",
"cluster_info_2": false,
}
}
"vcenter": "vcenter-2"
}
]
and add the new key/value pair "cluster_name":"<KEY_OF_PARENT_ELEMENT>" thus transforming the dict "datacenter_clusters" to a list.
The expected result should look like :
"list_of_dict": [
{
"datacenter": "DC_A",
"datacenter_clusters": [
{
"cluster_name": "CLUSTER_ALPHA",
"datacenter": "DC_A",
"cluster_info_1": "xxxxxx",
"cluster_info_2": true,
"hosts": [
{
"folder": "/path/to/host-1",
"name": "hostname-1"
},
{
"folder": "/path/to/host-2",
"name": "hostname-2"
}
]
},
{
"cluster_name": "CLUSTER_ALPHA",
"datacenter": "DC_A",
"cluster_info_1": "yyyyyyy",
"cluster_info_2": false,
}
]
"vcenter": "vcenter-1"
},
{
"datacenter": "DC_B",
"datacenter_clusters": [
{
"cluster_name": "CLUSTER_OMEGA"
"datacenter": "DC_B",
"cluster_info_1": "aaaaaaaa",
"cluster_info_2": true,
},
{
"cluster_name": "CLUSTER_ZETA"
"datacenter": "DC_A",
"cluster_info_1": "bbbbbbbbbb",
"cluster_info_2": false,
}
]
"vcenter": "vcenter-2"
}
]
I tried to combine what I found in this link with "with_subelements" but I couldn't loop through a list of dicts, I could only loop through a simple dict or a simple list or a list of lists.
Any help would be much appreciated

Multiple searches with with json_query/jmespath filter in Ansible

I'm trying to parse out specifc subnet names in the following piece of json, while using contains_with or starts_with filters in json_query.
It contains two vnets each of which has multiple subnets:
{
"azure_virtualnetworks": [
{
"name": "test-vnet-172-17-0-0-19",
"properties": {
"subnets": [
{
"name": "test-confluent-subnet-172-17-0-0-28",
"properties": {
"addressPrefix": "172.20.88.0/28",
"networkSecurityGroup": {
"id": "/subscriptions/********/resourceGroups/test-confluent-rg/providers/Microsoft.Network/networkSecurityGroups/test-confluent-nsg"
},
"provisioningState": "Succeeded"
}
},
{
"name": "test-test-subnet-172-17-0-32-28",
"properties": {
"addressPrefix": "172.20.88.32/28",
"networkSecurityGroup": {
"id": "/subscriptions/********/resourceGroups/test-test-rg/providers/Microsoft.Network/networkSecurityGroups/test-test-nsg"
},
"provisioningState": "Succeeded"
}
}
]
}
},
{
"name": "test2-vnet-172-17-1-0-19",
"properties": {
"subnets": [
{
"name": "test-confluent-subnet-172-17-1-0-28",
"properties": {
"addressPrefix": "172.20.88.0/28",
"networkSecurityGroup": {
"id": "/subscriptions/********/resourceGroups/test-confluent-rg/providers/Microsoft.Network/networkSecurityGroups/test-confluent-nsg"
},
"provisioningState": "Succeeded"
}
},
{
"name": "test-qatesting-subnet-172-17-1-16-28",
"properties": {
"addressPrefix": "172.20.88.16/28",
"networkSecurityGroup": {
"id": "/subscriptions/********/resourceGroups/test-qatesting-rg/providers/Microsoft.Network/networkSecurityGroups/test-qatesting-nsg"
},
"provisioningState": "Succeeded"
}
}
]
}
}
]
}
I need to search for a subnet name after searching by virtual network name.
I can filter as far down as the list of subnets without problems. e.g
azure_virtualnetworks[?contains(name,`test2-vnet`)].properties.subnets[]
returns:
[
{
"name": "test-confluent-subnet-172-17-1-0-28",
"properties": {
"addressPrefix": "172.20.88.0/28",
"networkSecurityGroup": {
"id": "/subscriptions/********/resourceGroups/test-confluent-rg/providers/Microsoft.Network/networkSecurityGroups/test-confluent-nsg"
},
"provisioningState": "Succeeded"
}
},
{
"name": "test-qatesting-subnet-172-17-1-16-28",
"properties": {
"addressPrefix": "172.20.88.16/28",
"networkSecurityGroup": {
"id": "/subscriptions/********/resourceGroups/test-qatesting-rg/providers/Microsoft.Network/networkSecurityGroups/test-qatesting-nsg"
},
"provisioningState": "Succeeded"
}
}
]
However I'm having problems then searching the subnets. I had thought that some variation on following might work but haven't had any sucess:
azure_virtualnetworks[?contains(name,`test2-vnet`)].properties.subnets[?contains(name,`test-confluent`) ]
I'm struggling to figure out what the correcting syntax is here.
Select required subnets, stop projection with pipe expression, filter required items from the subnets list:
azure_virtualnetworks[?contains(name,`test2-vnet`)].properties.subnets[] | [?contains(name,`test-confluent`)]

Fetch all user ids under domain

How do I fetch all user Ids under our company domain using Google API?
I want to get list of all users under our domain.
Then I want to get a list of all emails for each user.
I think you are referring to Retrieve all users in a domain:
To retrieve all users in the same domain, use the following GET request and include the authorization described in Authorize requests. For readability, this example uses line returns:
GET https://www.googleapis.com/admin/directory/v1/users
?domain=primary domain name&pageToken=token for next results page
&maxResults=max number of results per page
&orderBy=email, givenName, or familyName
&sortOrder=ascending or descending
&query=email, givenName, or familyName:the query's value*
By default, the system returns a list of 100 users in the alphabetical order of the user's email address:
GET https://www.googleapis.com/admin/directory/v1/users?domain=example.com&maxResults=2
A successful response returns an HTTP 200 status code. Along with the status code, the response returns 2 user accounts in the example.com domain (maxResults=2):
{
"kind": "directory#users",
"users": [
{
"kind": "directory#user",
"id": "the unique user id",
"primaryEmail": "liz#example.com",
"name": {
"givenName": "Liz",
"familyName": "Smith",
"fullName": "Liz Smith"
},
"isAdmin": true,
"isDelegatedAdmin": false,
"lastLoginTime": "2013-02-05T10:30:03.325Z",
"creationTime": "2010-04-05T17:30:04.325Z",
"agreedToTerms": true,
"hashFunction: "SHA-1",
"suspended": false,
"changePasswordAtNextLogin": false,
"ipWhitelisted": false,
"ims": [
{
"type": "work",
"protocol": "gtalk",
"im": "lizim#talk.example.com",
"primary": true
}
],
"emails": [
{
"address": "liz#example.com",
"type": "work",
"customType": "",
"primary": true
}
],
"addresses": [
{
"type": "work",
"customType": "",
"streetAddress": "1600 Amphitheatre Parkway",
"locality": "Mountain View",
"region": "CA",
"postalCode": "94043"
}
],
"externalIds": [
{
"value": "employee number",
"type": "custom",
"customType": "office"
}
],
"relations": [
{
"value": "susan",
"type": "friend",
"customType": ""
}
],
"organizations": [
{
"name": "Google Inc.",
"title": "SWE",
"primary": true,
"customType": "",
"description": "Software engineer"
}
],
"phones": [
{
"value": "+1 nnn nnn nnnn",
"type": "work"
}
],
"aliases": [
"lizsmith#example.com",
"lsmith#example.com"
],
"nonEditableAliases: [
"liz#test.com"
],
"customerId": "C03az79cb",
"orgUnitPath": "corp/engineering",
"isMailboxSetup": true,
"includeInGlobalAddressList": true
},
{
"kind": "directory#user",
"id": "user unique ID",
"primaryEmail": "admin2#example.com",
"name": {
"givenName": "admin",
"familyName": "two",
"fullName": "admin two"
},
"isAdmin": true,
"isDelegatedAdmin": true,
"lastLoginTime": "2013-02-05T10:30:03.325Z",
"creationTime": "2010-04-05T17:30:04.325Z",
"agreedToTerms": true,
"hashFunction: "SHA-1",
"suspended": true,
"suspensionReason": "ADMIN",
"changePasswordAtNextLogin": false,
"ipWhitelisted": false,
"emails": [
{
"address": "admin2#example.com",
"type": "work",
"customType": "",
"primary": true
}
],
"externalIds": [
{
"value": "contractor license number",
"type": "custom",
"customType": "work"
}
],
"relations": [
{
"value": "liz",
"type": "friend",
"customType": ""
}
],
"aliases": [
"second_admin#example.com"
],
"nonEditableAliases: [
"admin#test.com"
],
"customerId": "C03az79cb",
"orgUnitPath": "corp/engineering",
"isMailboxSetup": true,
"includeInGlobalAddressList": true
}
],
"nextPageToken": "next page token"
}
You can also check out Retrieve all account users
To retrieve all users in an account which can consist of multiple domains, use the following GET request and include the authorization described in Authorize requests.

Combine JSON objects in Ruby, and output to CSV

Let's say I have two JSON objects (call them 'websites' and 'links'). I need to end up with both objects in a single CSV (ideally in separate columns).
I'm working with something like this:
File.open("file.json", "w") do |f|
combined = [websites, links]
f.write(JSON.pretty_generate(combined))
end
And then I'm using the Ruby gem json2csv to convert this file to a CSV. But when I do, I get the following error:
error: undefined method 'keys' for #<Array:0x007fea8a8e33f8>
I can't figure out what's wrong. When I look in file.json, it appears to be structured like this: [{websites}, {links}]. From my limited knowledge of JSON, I think that's right, but I could easily be wrong.
Also, I know this won't get me separate columns in the CSV. If anyone has an answer for that part, major bonus points.
EDIT: JSON examples included below; error message changed after minor fix on my end.
websites:
{
"uri": "https://v1/websites",
"id": 28235674,
"background": null,
"createdDate": 1399585684000,
"lastActivityDate": 1430682494000,
"lastCommunicationDate": 1430682494000,
"lastNonCommunicationChronicleDate": 1430330886000,
"lastModifiedDate": 1449263116000,
"lastViewedDate": 1421429034000,
"preferredContactType": null,
"rss": "",
"emailAddresses": [
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "not found",
"type": "Work"
}
],
"phoneNumbers": [
],
"streetAddresses": [
],
"socialNetworks": [
{
"profileUrl": "http://twitter.com",
"name": "Twitter"
},
{
"profileUrl": "http://www.facebook.com",
"name": "Facebook"
},
{
"profileUrl": "http://plus.google.com",
"name": "GooglePlus"
},
{
"profileUrl": "http://www.linkedin.com",
"name": "LinkedIn"
},
{
"profileUrl": "http://twitter.com",
"name": "Twitter"
}
],
"contactUrls": [
],
"tags": [
"tag1",
"tag2"
],
"mostRecentActivity": "https://v1/history",
"mostRecentChronicle": "https://v1/history",
"mostRecentCommunication": "https://v1/history",
"mostRecentNonCommunicationChronicle": "https://v1/history",
"projectStates": "https://v1/websites",
"history": "https://v1/history",
"customFieldValues": [
],
"name": "",
"primaryDomain": "",
"domains": [
""
],
"associatedPeople": "https://v1/people",
"payments": "https://payments",
"links": "https://v1/links",
"type": "https://v1/websites"
}
links:
{
"uri": "https://v1/links/custom_fields",
"id": 15529329,
"value": "Name",
"backgroundColor": null,
"customField": "https://v1/links/custom_fields"
}
combined output:
[
{
"uri": "https://v1/websites",
"id": 28235674,
"background": null,
"createdDate": 1399585684000,
"lastActivityDate": 1430682494000,
"lastCommunicationDate": 1430682494000,
"lastNonCommunicationChronicleDate": 1430330886000,
"lastModifiedDate": 1449263116000,
"lastViewedDate": 1421429034000,
"preferredContactType": null,
"rss": "",
"emailAddresses": [
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "",
"type": "Work"
},
{
"email": "not found",
"type": "Work"
}
],
"phoneNumbers": [
],
"streetAddresses": [
],
"socialNetworks": [
{
"profileUrl": "http://twitter.com/",
"name": "Twitter"
},
{
"profileUrl": "http://www.facebook.com",
"name": "Facebook"
},
{
"profileUrl": "http://plus.google.com",
"name": "GooglePlus"
},
{
"profileUrl": "http://www.linkedin.com/",
"name": "LinkedIn"
},
{
"profileUrl": "http://twitter.com/",
"name": "Twitter"
}
],
"contactUrls": [
],
"tags": [
"tag1",
"tag2"
],
"mostRecentActivity": "https://v1/history/",
"mostRecentChronicle": "https://v1/history/",
"mostRecentCommunication": "https://v1/history/",
"mostRecentNonCommunicationChronicle": "https://v1/history/",
"projectStates": "https://v1/websites/",
"history": "https://v1/history",
"customFieldValues": [
],
"name": "",
"primaryDomain": "",
"domains": [
""
],
"associatedPeople": "https://v1/people",
"links": "https://v1/links",
"type": "https://v1/websites"
},
{
"uri": "https://links/custom_fields",
"id": 15529329,
"value": "Name",
"backgroundColor": null,
"customField": "https://links/custom_fields"
}
]
JSON.pretty_generate() is expecting a hash and you are passing an array of 2 hashes. Start with: combined.map { |c| f.write(JSON.pretty_generate(c)) } and then mapping them into your CSV should be as easy as following the CSV documentation.

Resources