Related
So I am following this AWS blog to enforce tagging policy across AWS Organization.
I did create the tag policy and the SCP and attached both to the OUs.
Tag policy
{
"tags": {
"costcenter": {
"tag_key": {
"##assign": "costcenter"
},
"tag_value": {
"##assign": [
"CC102",
"CC103",
"CC104"
]
},
"enforced_for": {
"##assign": [
"ec2:instance"
]
}
},
"team": {
"tag_key": {
"##assign": "team"
},
"tag_value": {
"##assign": [
"Team1",
"Team2",
"Team3"
]
},
"enforced_for": {
"##assign": [
"ec2:instance"
]
}
}
}
}
SCP
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyEC2CreationSCP1",
"Effect": "Deny",
"Action": [
"ec2:RunInstances"
],
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"Null": {
"aws:RequestTag/costcenter": "true"
}
}
},
{
"Sid": "Statement1",
"Effect": "Deny",
"Action": [
"ec2:RunInstances"
],
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"Null": {
"aws:RequestTag/team": "true"
}
}
}
]
}
When I try to launch an EC2 with non compliant tags, I get the error not authorized with clear message about violating the tag policy
using non compliant tags error
but even when I comply to the policy I get the non authorized message
using compliant tags error
Here is the decoded message
{
"DecodedMessage": "{\"allowed\":false,\"explicitDeny\":true,\"matchedStatements\":{\"items\":[{\"statementId\":\"DenyEC2CreationSCP1\",\"effect\":\"DENY\",\"principals\":{\"items\":[{\"value\":\"AROAY4Z6JOQ4EEGF437YJ\"}]},\"principalGroups\":{\"items\":[]},\"actions\":{\"items\":[{\"value\":\"ec2:RunInstances\"}]},\"resources\":{\"items\":[{\"value\":\"arn:aws:ec2:*:*:instance/*\"},{\"value\":\"arn:aws:ec2:*:*:volume/*\"}]},\"conditions\":{\"items\":[{\"key\":\"aws:RequestTag/costcenter\",\"values\":{\"items\":[{\"value\":\"true\"}]}}]}},{\"statementId\":\"Statement1\",\"effect\":\"DENY\",\"principals\":{\"items\":[{\"value\":\"AROAY4Z6JOQ4EEGF437YJ\"}]},\"principalGroups\":{\"items\":[]},\"actions\":{\"items\":[{\"value\":\"ec2:RunInstances\"}]},\"resources\":{\"items\":[{\"value\":\"arn:aws:ec2:*:*:instance/*\"},{\"value\":\"arn:aws:ec2:*:*:volume/*\"}]},\"conditions\":{\"items\":[{\"key\":\"aws:RequestTag/team\",\"values\":{\"items\":[{\"value\":\"true\"}]}}]}},{\"statementId\":\"DenyEC2CreationSCP1\",\"effect\":\"DENY\",\"principals\":{\"items\":[{\"value\":\"AROAY4Z6JOQ4EEGF437YJ\"}]},\"principalGroups\":{\"items\":[]},\"actions\":{\"items\":[{\"value\":\"ec2:RunInstances\"}]},\"resources\":{\"items\":[{\"value\":\"arn:aws:ec2:*:*:instance/*\"},{\"value\":\"arn:aws:ec2:*:*:volume/*\"}]},\"conditions\":{\"items\":[{\"key\":\"aws:RequestTag/costcenter\",\"values\":{\"items\":[{\"value\":\"true\"}]}}]}},{\"statementId\":\"Statement1\",\"effect\":\"DENY\",\"principals\":{\"items\":[{\"value\":\"AROAY4Z6JOQ4EEGF437YJ\"}]},\"principalGroups\":{\"items\":[]},\"actions\":{\"items\":[{\"value\":\"ec2:RunInstances\"}]},\"resources\":{\"items\":[{\"value\":\"arn:aws:ec2:*:*:instance/*\"},{\"value\":\"arn:aws:ec2:*:*:volume/*\"}]},\"conditions\":{\"items\":[{\"key\":\"aws:RequestTag/team\",\"values\":{\"items\":[{\"value\":\"true\"}]}}]}}]},\"failures\":{\"items\":[]},\"context\":{\"principal\":{\"id\":\"AROAY4Z6JOQ4EEGF437YJ:nejla\",\"arn\":\"arn:aws:sts::random-account-number:assumed-role/OrganizationAccountAccessRole/nejla\"},\"action\":\"ec2:RunInstances\",\"resource\":\"arn:aws:ec2:us-east-1:random-account-number:volume/*\",\"conditions\":{\"items\":[{\"key\":\"aws:Resource\",\"values\":{\"items\":[{\"value\":\"volume/*\"}]}},{\"key\":\"aws:Account\",\"values\":{\"items\":[{\"value\":\"random-account-number\"}]}},{\"key\":\"ec2:AvailabilityZone\",\"values\":{\"items\":[{\"value\":\"us-east-1e\"}]}},{\"key\":\"ec2:Encrypted\",\"values\":{\"items\":[{\"value\":\"false\"}]}},{\"key\":\"ec2:VolumeType\",\"values\":{\"items\":[{\"value\":\"gp2\"}]}},{\"key\":\"ec2:IsLaunchTemplateResource\",\"values\":{\"items\":[{\"value\":\"false\"}]}},{\"key\":\"aws:Region\",\"values\":{\"items\":[{\"value\":\"us-east-1\"}]}},{\"key\":\"aws:Service\",\"values\":{\"items\":[{\"value\":\"ec2\"}]}},{\"key\":\"ec2:VolumeID\",\"values\":{\"items\":[{\"value\":\"*\"}]}},{\"key\":\"ec2:VolumeSize\",\"values\":{\"items\":[{\"value\":\"8\"}]}},{\"key\":\"ec2:ParentSnapshot\",\"values\":{\"items\":[{\"value\":\"arn:aws:ec2:us-east-1::snapshot/snap-0c371a5504a01769d\"}]}},{\"key\":\"aws:Type\",\"values\":{\"items\":[{\"value\":\"volume\"}]}},{\"key\":\"ec2:Region\",\"values\":{\"items\":[{\"value\":\"us-east-1\"}]}},{\"key\":\"aws:ARN\",\"values\":{\"items\":[{\"value\":\"arn:aws:ec2:us-east-1:random-account-number:volume/*\"}]}}]}}}"
}
Desired outcomes
The decoded message clearly says there is an explicit denial from your SCP policies. (You should mask your AWS account id)
{
"allowed": false,
"explicitDeny": true,
"matchedStatements": {
"items": [
{
"statementId": "DenyEC2CreationSCP1",
"effect": "DENY",
"principals": {
"items": [
{
"value": "AROAY4Z6JOQ4EEGF437YJ"
}
]
},
"principalGroups": {
"items": []
},
"actions": {
"items": [
{
"value": "ec2:RunInstances"
}
]
},
"resources": {
"items": [
{
"value": "arn:aws:ec2:*:*:instance/*"
},
{
"value": "arn:aws:ec2:*:*:volume/*"
}
]
},
"conditions": {
"items": [
{
"key": "aws:RequestTag/costcenter",
"values": {
"items": [
{
"value": "true"
}
]
}
}
]
}
},
{
"statementId": "Statement1",
"effect": "DENY",
"principals": {
"items": [
{
"value": "AROAY4Z6JOQ4EEGF437YJ"
}
]
},
"principalGroups": {
"items": []
},
"actions": {
"items": [
{
"value": "ec2:RunInstances"
}
]
},
"resources": {
"items": [
{
"value": "arn:aws:ec2:*:*:instance/*"
},
{
"value": "arn:aws:ec2:*:*:volume/*"
}
]
},
"conditions": {
"items": [
{
"key": "aws:RequestTag/team",
"values": {
"items": [
{
"value": "true"
}
]
}
}
]
}
},
{
"statementId": "DenyEC2CreationSCP1",
"effect": "DENY",
"principals": {
"items": [
{
"value": "AROAY4Z6JOQ4EEGF437YJ"
}
]
},
"principalGroups": {
"items": []
},
"actions": {
"items": [
{
"value": "ec2:RunInstances"
}
]
},
"resources": {
"items": [
{
"value": "arn:aws:ec2:*:*:instance/*"
},
{
"value": "arn:aws:ec2:*:*:volume/*"
}
]
},
"conditions": {
"items": [
{
"key": "aws:RequestTag/costcenter",
"values": {
"items": [
{
"value": "true"
}
]
}
}
]
}
},
{
"statementId": "Statement1",
"effect": "DENY",
"principals": {
"items": [
{
"value": "AROAY4Z6JOQ4EEGF437YJ"
}
]
},
"principalGroups": {
"items": []
},
"actions": {
"items": [
{
"value": "ec2:RunInstances"
}
]
},
"resources": {
"items": [
{
"value": "arn:aws:ec2:*:*:instance/*"
},
{
"value": "arn:aws:ec2:*:*:volume/*"
}
]
},
"conditions": {
"items": [
{
"key": "aws:RequestTag/team",
"values": {
"items": [
{
"value": "true"
}
]
}
}
]
}
}
]
},
"failures": {
"items": []
},
"context": {
"principal": {
"id": "AROAY4Z6JOQ4EEGF437YJ:nejla",
"arn": "arn:aws:sts::123456789:assumed-role/OrganizationAccountAccessRole/nejla"
},
"action": "ec2:RunInstances",
"resource": "arn:aws:ec2:us-east-1:123456789:volume/*",
"conditions": {
"items": [
{
"key": "aws:Resource",
"values": {
"items": [
{
"value": "volume/*"
}
]
}
},
{
"key": "aws:Account",
"values": {
"items": [
{
"value": "123456789"
}
]
}
},
{
"key": "ec2:AvailabilityZone",
"values": {
"items": [
{
"value": "us-east-1e"
}
]
}
},
{
"key": "ec2:Encrypted",
"values": {
"items": [
{
"value": "false"
}
]
}
},
{
"key": "ec2:VolumeType",
"values": {
"items": [
{
"value": "gp2"
}
]
}
},
{
"key": "ec2:IsLaunchTemplateResource",
"values": {
"items": [
{
"value": "false"
}
]
}
},
{
"key": "aws:Region",
"values": {
"items": [
{
"value": "us-east-1"
}
]
}
},
{
"key": "aws:Service",
"values": {
"items": [
{
"value": "ec2"
}
]
}
},
{
"key": "ec2:VolumeID",
"values": {
"items": [
{
"value": "*"
}
]
}
},
{
"key": "ec2:VolumeSize",
"values": {
"items": [
{
"value": "8"
}
]
}
},
{
"key": "ec2:ParentSnapshot",
"values": {
"items": [
{
"value": "arn:aws:ec2:us-east-1::snapshot/snap-0c371a5504a01769d"
}
]
}
},
{
"key": "aws:Type",
"values": {
"items": [
{
"value": "volume"
}
]
}
},
{
"key": "ec2:Region",
"values": {
"items": [
{
"value": "us-east-1"
}
]
}
},
{
"key": "aws:ARN",
"values": {
"items": [
{
"value": "arn:aws:ec2:us-east-1:123456789:volume/*"
}
]
}
}
]
}
}
}
Please make sure you are using the policies with the correct conditions, if there is any explicit denial in the policies, it always takes a high priority.
I have tried to bulk add a contact using API Try editor of Google https://developers.google.com/people/api/rest/v1/people/batchCreateContacts
{
"contacts": [
{
"contactPerson": {
"addresses": [
{
"formattedValue": "formattedValue",
"type": "type",
"poBox": "poBox",
"streetAddress": "streetAddress",
"extendedAddress": "extendedAddress",
"region": "region",
"postalCode": "postalCode",
"country": "country",
"countryCode": "countryCode"
},
{
"formattedValue": "formattedValue",
"type": "type",
"poBox": "poBox",
"streetAddress": "streetAddress",
"extendedAddress": "extendedAddress",
"city": "city",
"region": "region",
"postalCode": "postalCode",
"country": "country",
"countryCode": "countryCode"
}
],
"biographies": [
{
"value": "biographies-value",
"contentType": "TEXT_PLAIN"
}
],
"birthdays": [
{
"date": {
"year": 1988,
"month": 9,
"day": 22
},
"text": "22/09/1988"
}
],
"calendarUrls": [
{
"url": "https://lh3.googleusercontent.com/ogw/ADea4I4kLm9hsAYNpD_7v-7wXki3joED-eg2ZHcGmp31",
"type": "calendarUrls-type"
}
],
"clientData": [
{
"key": "clientData-key",
"value": "clientData-value"
}
],
"emailAddresses": [
{
"value": "emailAddresses-value",
"type": "emailAddresses-type",
"displayName": "emailAddresses-displayName"
}
],
"events": [
{
"date": {
"year": 1988,
"month": 9,
"day": 22
},
"type": "events-type"
},
{
"date": {
"year": 1988,
"month": 9,
"day": 22
},
"type": "events-type"
},
{
"date": {
"year": 2019,
"month": 12,
"day": 7
},
"type": "marriage"
}
],
"externalIds": [
{
"value": "externalIds-value",
"type": "externalIds-type"
}
],
"fileAses": [
{
"value": "fileAses-value"
}
],
"genders": [
{
"value": "male",
"addressMeAs": "her"
}
],
"imClients": [
{
"username": "imClients-username1",
"type": "imClients-typeA",
"protocol": "imClients-protocol1"
},
{
"username": "imClients-username2",
"type": "imClients-typeA",
"protocol": "imClients-protocol2"
},
{
"username": "imClients-username3",
"type": "imClients-typeB",
"protocol": "imClients-protocol3"
}
],
"interests": [
{
"value": "interests-value"
}
],
"locales": [
{
"value": "locales-value"
}
],
"locations": [
{
"value": "locations-value1",
"type": "desk",
"current": true,
"buildingId": "locations-buildingId",
"floor": "locations-floor",
"floorSection": "buildingId-floorSection",
"deskCode": "locations-deskCode"
},
{
"value": "locations-value2",
"type": "desk",
"current": true,
"buildingId": "locations-buildingId",
"floor": "locations-floor",
"floorSection": "buildingId-floorSection",
"deskCode": "locations-deskCode"
}
],
"memberships": [
{
"contactGroupMembership": {
"contactGroupResourceName": "contactGroups/3616ed318c1125e3"
}
}
],
"miscKeywords": [
{
"value": "SENSITIVITY1",
"type": "OUTLOOK_SENSITIVITY"
},
{
"value": "SENSITIVITY2",
"type": "OUTLOOK_SENSITIVITY"
},
{
"value": "OUTLOOK_SUBJECT",
"type": "OUTLOOK_SUBJECT"
},
{
"value": "OUTLOOK_BILLING_INFORMATION",
"type": "OUTLOOK_BILLING_INFORMATION"
},
{
"value": "OUTLOOK_DIRECTORY_SERVER",
"type": "OUTLOOK_DIRECTORY_SERVER"
},
{
"value": "OUTLOOK_KEYWORD",
"type": "OUTLOOK_KEYWORD"
},
{
"value": "OUTLOOK_MILEAGE",
"type": "OUTLOOK_MILEAGE"
},
{
"value": "OUTLOOK_PRIORITY",
"type": "OUTLOOK_PRIORITY"
},
{
"value": "OUTLOOK_SUBJECT",
"type": "OUTLOOK_SUBJECT"
},
{
"value": "OUTLOOK_USER1-value",
"type": "OUTLOOK_USER"
},
{
"value": "OUTLOOK_USER2-value",
"type": "OUTLOOK_USER"
},
{
"value": "HOME",
"type": "HOME"
},
{
"value": "WORK",
"type": "WORK"
},
{
"value": "OTHER",
"type": "OTHER"
}
],
"names": [
{
"unstructuredName": "unstructuredName",
"familyName": "MrTest",
"givenName": "givenName",
"middleName": "middleName",
"honorificPrefix": "honorificPrefix",
"honorificSuffix": "honorificSuffix",
"phoneticFullName": "phoneticFullName",
"phoneticFamilyName": "phoneticFamilyName",
"phoneticGivenName": "phoneticGivenName",
"phoneticMiddleName": "phoneticMiddleName",
"phoneticHonorificPrefix": "phoneticHonorificPrefix",
"phoneticHonorificSuffix": "phoneticHonorificSuffix"
}
],
"nicknames": [
{
"value": "nicknames-value-alternate-name",
"type": "ALTERNATE_NAME"
},
{
"value": "nicknames-value-default",
"type": "DEFAULT"
}
],
"occupations": [
{
"value": "occupations-value"
}
],
"organizations": [
{
"type": "organizations-type",
"startDate": {
"year": 1988,
"month": 9,
"day": 22
},
"endDate": {
"year": 1988,
"month": 9,
"day": 22
},
"current": true,
"name": "organizations-name",
"phoneticName": "organizations-phoneticName",
"department": "organizations-department",
"title": "organizations-title",
"jobDescription": "organizations-jobDescription",
"symbol": "organizations-symbol",
"domain": "organizations-domain",
"location": "organizations-location"
}
],
"phoneNumbers": [
{
"value": "phoneNumbers-value",
"type": "phoneNumbers-type"
}
],
"relations": [
{
"person": "relations-person",
"type": "relations-type"
}
],
"sipAddresses": [
{
"value": "sipAddresses-value",
"type": "sipAddresses-type"
}
],
"urls": [
{
"value": "https://lh3.googleusercontent.com/ogw/ADea4I4kLm9hsAYNpD_7v-7wXki3joED-eg2ZHcGmp31",
"type": "urls-type"
}
],
"userDefined": [
{
"key": "userDefined-key",
"value": "userDefined-value"
}
]
}
}
],
"readMask": "emailAddresses,phoneNumbers,addresses,birthdays,biographies,calendarUrls,clientData,coverPhotos,events,externalIds,genders,imClients,interests,locales,locations,memberships,miscKeywords,names,nicknames,occupations,organizations,phoneNumbers,photos,relations,sipAddresses,skills,urls,userDefined"
}
I get the error as
{
"error": {
"code": 500,
"message": "Internal error encountered.",
"status": "INTERNAL"
}
}
Am I missing something?
It looks like the 500 Internal Error message you are receiving is due to the fact that you are using the calendarUrls field in the request.
This might in fact be a bug so I have taken the opportunity to file a report on Google's Issue Tracker here.
I suggest you star the issue as all the updates will be posted there.
I'm extending Istio to provide Thrift features. The Istio component I'm working on right now is Pilot (Envoy config service). I've extended it with basic Thrift routing so that it can provide an Envoy configuration to route a listener to the correct cluster. My development environment looks something like:
Now I'm trying to add rate limiting. I'm following the docs. I've patched my config with a RouteAction that doesn't get applied, because there is no rate limit filter. This works fine, and passes traffic as before:
...
{
"filters": [
{
"name": "envoy.filters.network.thrift_proxy",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.network.thrift_proxy.v2alpha1.ThriftProxy",
"stat_prefix": "10.97.28.169_9090",
"transport": "HEADER",
"protocol": "BINARY",
"route_config": {
"name": "outbound|9090||backend.default.svc.cluster.local",
"routes": [
{
"match": {
"method_name": ""
},
"route": {
"cluster": "outbound|9090||backend.default.svc.cluster.local",
"rate_limits": [
{
"actions": [
{
"request_headers": {
"header_name": ":method-name",
"descriptor_key": "method-name"
}
}
]
}
]
}
}
]
}
}
}
]
}
],
"deprecated_v1": {
"bind_to_port": false
},
"listener_filters_timeout": "0.100s",
"traffic_direction": "OUTBOUND",
"continue_on_listener_filters_timeout": true
},
"last_updated": "2019-10-30T16:26:39.203Z"
},
...
I've built a function to create an envoy.filters.thrift.rate_limit filter that makes Envoy to call the rate limit service I've set up (I've tried both GoogleGrpc and EnvoyGrpc):
func buildThriftRatelimit(ratelimitServiceUri, domain string) *thrift_ratelimit.RateLimit {
var thriftRateLimit *thrift_ratelimit.RateLimit
timeout := 2000 * time.Millisecond
thriftRateLimit = &thrift_ratelimit.RateLimit{
Domain: domain,
Timeout: &timeout,
FailureModeDeny: false,
RateLimitService: &ratelimit.RateLimitServiceConfig{
GrpcService: &core.GrpcService{
TargetSpecifier: &core.GrpcService_GoogleGrpc_{
GoogleGrpc: &core.GrpcService_GoogleGrpc{
StatPrefix: ratelimitServiceUri,
TargetUri: ratelimitServiceUri,
},
},
},
},
}
thriftRateLimit.Validate()
if err := thriftRateLimit.Validate(); err != nil {
panic(err)
}
return thriftRateLimit
}
Which produces:
...
{
"filters": [
{
"name": "envoy.filters.network.thrift_proxy",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.network.thrift_proxy.v2alpha1.ThriftProxy",
"stat_prefix": "10.97.28.169_9090",
"transport": "HEADER",
"protocol": "BINARY",
"route_config": {
"name": "outbound|9090||backend.default.svc.cluster.local",
"routes": [
{
"match": {
"method_name": ""
},
"route": {
"cluster": "outbound|9090||backend.default.svc.cluster.local",
"rate_limits": [
{
"actions": [
{
"request_headers": {
"header_name": ":method-name",
"descriptor_key": "method-name"
}
}
]
}
]
}
}
]
},
"thrift_filters": [
{
"name": "envoy.filters.thrift.rate_limit",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.thrift.rate_limit.v2alpha1.RateLimit",
"domain": "backend.default.svc.cluster.local",
"timeout": "2s",
"rate_limit_service": {
"grpc_service": {
"google_grpc": {
"target_uri": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80",
"stat_prefix": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80"
}
}
}
}
}
]
}
}
]
}
],
"deprecated_v1": {
"bind_to_port": false
},
"listener_filters_timeout": "0.100s",
"traffic_direction": "OUTBOUND",
"continue_on_listener_filters_timeout": true
},
"last_updated": "2019-10-30T16:26:39.203Z"
},
...
When the rate limit filter is applied, connections to the backend die and no error is returned to the client or displayed in Envoy's logs.
If Thrift filters are provided, you need to add the Router filter as the last filter in the chain like so:
...
{
"filters": [
{
"name": "envoy.filters.network.thrift_proxy",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.network.thrift_proxy.v2alpha1.ThriftProxy",
"stat_prefix": "10.97.28.169_9090",
"transport": "HEADER",
"protocol": "BINARY",
"route_config": {
"name": "outbound|9090||backend.default.svc.cluster.local",
"routes": [
{
"match": {
"method_name": ""
},
"route": {
"cluster": "outbound|9090||backend.default.svc.cluster.local",
"rate_limits": [
{
"actions": [
{
"request_headers": {
"header_name": ":method-name",
"descriptor_key": "method-name"
}
}
]
}
]
}
}
]
},
"thrift_filters": [
{
"name": "envoy.filters.thrift.rate_limit",
"typed_config": {
"#type": "type.googleapis.com/envoy.config.filter.thrift.rate_limit.v2alpha1.RateLimit",
"domain": "backend.default.svc.cluster.local",
"timeout": "2s",
"rate_limit_service": {
"grpc_service": {
"google_grpc": {
"target_uri": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80",
"stat_prefix": "istio-lyft-ratelimit.istio-system.svc.cluster.local:80"
}
}
}
}
},
{
"name": "envoy.filters.thrift.router"
}
]
}
}
]
}
],
"deprecated_v1": {
"bind_to_port": false
},
"listener_filters_timeout": "0.100s",
"traffic_direction": "OUTBOUND",
"continue_on_listener_filters_timeout": true
},
"last_updated": "2019-10-30T16:26:39.203Z"
},
...
I am trying to create an api model from a swagger file (my-api.json) using Loopback's Swagger connector (assuming that's what this connector is for!).
However, when running the loopback-cli, I get the following error:
? Enter the swagger spec url or file path: my-api.json
Loading my-api.json...
events.js:183
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property '$ref' of null
at C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\generator-loopback\swagger\spec-loader.js:124:13
at baseClone (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:2641:27)
at C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:2711:34
at arrayEach (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:516:11)
at baseClone (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:2705:7)
at C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:2711:34
at arrayEach (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:516:11)
at baseClone (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:2705:7)
at Function.cloneDeepWith (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\lodash\lodash.js:11120:14)
at parseSpec (C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\generator-loopback\swagger\spec-loader.js:123:19)
at C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\generator-loopback\swagger\spec-loader.js:160:5
at C:\Users\Nick\AppData\Roaming\npm\node_modules\loopback-cli\node_modules\generator-loopback\swagger\spec-loader.js:86:11
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:511:3)
Here's the my-api-json swagger file:
{
"swagger": "2.0",
"info": {
"description": "my description",
"version": "0.0.2",
"title": "my title",
"termsOfService": "TBD",
"contact": {
"name": "John Doe",
"url": "http://www.myname.com",
"email": "johndoe#aol.com"
},
"license": {
"name": "TBD",
"url": "http://www.myname.com"
},
"x-classificationRecord": "Classsification of this swagger file - APPROVED"
},
"basePath": "/myPath",
"schemes": [
"http",
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"securityDefinitions": {
"AdminSecurity": {
"type": "apiKey",
"in": "query",
"name": "apikey"
}
},
"paths": {
"/admin/vcap": {
"get": {
"tags": [
"admin"
],
"security": [
{
"AdminSecurity": []
}
],
"x-swagger-router-controller": "misc_info_controller",
"operationId": "getVCAP",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllTopicEntity": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllTopicEntity",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllTopic": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllTopic",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllEntityFacets": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllEntityFacets",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllTopicEntityFacets": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllTopicEntityFacets",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllTopicEntityRelation": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllTopicEntityRelation",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllTopicPropertyFacet": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllTopicPropertyFacet",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAllTable13": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAllTable13",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAlltblComponentType": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAlltblComponentType",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAlltblElement": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAlltblElement",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAlltblFeature": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAlltblFeature",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAlltblSymbolPlacementInst": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAlltblSymbolPlacementInst",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAlltblSymbolElementLink": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAlltblSymbolElementLink",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/getAlltblSymol": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "getAlltblSymol",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/query/newQuery": {
"get": {
"tags": [
"database"
],
"x-swagger-router-controller": "db",
"operationId": "newQuery",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success"
}
}
}
}
},
"definitions": {
"Generic": {
"properties": {
"message": {
"type": "string"
}
}
},
"GenericError": {
"required": [
"status",
"statusCode",
"error"
],
"properties": {
"status": {
"type": "string",
"description": "Status indicating there was an error, should always be error",
"enum": [
"error"
]
},
"statusCode": {
"type": "number",
"description": "HTTP Status Code for the error"
},
"error": {
"type": "string",
"description": "String indicating what the error was"
},
"trace": {
"type": "string",
"description": "Original Error Message providing more detail if available"
}
}
},
"ErrorResponse": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer"
},
"message": {
"type": "string"
}
}
}
}
}
Any tips on how to fix? Thank you.
I followed this link :
https://developers.google.com/assistant/sdk/guides/service/python/extend/custom-actions
And I successfully create three actions files. and it works individually. but when I test all together like deploying three action packages:
./gactions update --action_package MqttAct.json --action_package action.json --action_package MesureTemp.json --project rpi3-0001-ga-******
I found that only two packages will work. it's like we can't have more than two action packages?
I'm surprised you can even deploy two packages at the same time. The idea is that you have one action package, which can contain a variety of actions merged together.
Here is a merged action package, based on the documentation:
{
"manifest": {
"displayName": "Blinky light",
"invocationName": "Blinky light",
"category": "PRODUCTIVITY"
},
"actions": [
{
"name": "com.example.actions.BlinkLight",
"availability": {
"deviceClasses": [
{
"assistantSdkDevice": {}
}
]
},
"intent": {
"name": "com.example.intents.BlinkLight",
"parameters": [
{
"name": "number",
"type": "SchemaOrg_Number"
},
{
"name": "speed",
"type": "Speed"
}
],
"trigger": {
"queryPatterns": [
"blink ($Speed:speed)? $SchemaOrg_Number:number times",
"blink $SchemaOrg_Number:number times ($Speed:speed)?"
]
}
},
"fulfillment": {
"staticFulfillment": {
"templatedResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Blinking $number times"
}
},
{
"deviceExecution": {
"command": "com.example.commands.BlinkLight",
"params": {
"speed": "$speed",
"number": "$number"
}
}
}
]
}
}
}
},
{
"name": "com.example.actions.BlonkLight",
"availability": {
"deviceClasses": [
{
"assistantSdkDevice": {}
}
]
},
"intent": {
"name": "com.example.intents.BlonkLight",
"parameters": [
{
"name": "number",
"type": "SchemaOrg_Number"
},
{
"name": "speed",
"type": "Speed"
}
],
"trigger": {
"queryPatterns": [
"blonk ($Speed:speed)? $SchemaOrg_Number:number times",
"blonk $SchemaOrg_Number:number times ($Speed:speed)?"
]
}
},
"fulfillment": {
"staticFulfillment": {
"templatedResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Blonking $number times"
}
},
{
"deviceExecution": {
"command": "com.example.commands.BlonkLight",
"params": {
"speed": "$speed",
"number": "$number"
}
}
}
]
}
}
}
}
],
"types": [
{
"name": "$Speed",
"entities": [
{
"key": "slowly",
"synonyms": [
"slowly",
"slow"
]
},
{
"key": "normally",
"synonyms": [
"normally",
"regular"
]
},
{
"key": "quickly",
"synonyms": [
"quickly",
"fast",
"quick"
]
}
]
}
]
}