Add the container API to our dependencies.

Update google-api-go-client
pull/6/head
Brendan Burns 2014-11-13 12:34:44 -08:00
parent aabf1c3573
commit d3e48c9525
19 changed files with 4442 additions and 78 deletions

11
Godeps/Godeps.json generated
View File

@ -1,6 +1,6 @@
{
"ImportPath": "github.com/GoogleCloudPlatform/kubernetes",
"GoVersion": "go1.3.1",
"GoVersion": "go1.3",
"Packages": [
"./..."
],
@ -42,12 +42,17 @@
{
"ImportPath": "code.google.com/p/google-api-go-client/compute/v1",
"Comment": "release-96",
"Rev": "0923cdda5b82a7dd0dd5c689f824ca5e7d9b60de"
"Rev": "98c78185197025f935947caac56a7b6d022f89d2"
},
{
"ImportPath": "code.google.com/p/google-api-go-client/container/v1beta1",
"Comment": "release-105",
"Rev": "98c78185197025f935947caac56a7b6d022f89d2"
},
{
"ImportPath": "code.google.com/p/google-api-go-client/googleapi",
"Comment": "release-96",
"Rev": "0923cdda5b82a7dd0dd5c689f824ca5e7d9b60de"
"Rev": "98c78185197025f935947caac56a7b6d022f89d2"
},
{
"ImportPath": "github.com/coreos/go-etcd/etcd",

View File

@ -0,0 +1,10 @@
# This is the official list of authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as
# Name or Organization <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
Google Inc.

View File

@ -0,0 +1,46 @@
# This is the official list of people who can contribute
# (and typically have contributed) code to the repository.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# The submission process automatically checks to make sure
# that people submitting code are listed in this file (by email address).
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# http://code.google.com/legal/individual-cla-v1.0.html
# http://code.google.com/legal/corporate-cla-v1.0.html
#
# The agreement for individuals can be filled out on the web.
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
# Names should be added to this file like so:
# Name <email address>
#
# An entry with two email addresses specifies that the
# first address should be used in the submit logs and
# that the second address should be recognized as the
# same person when interacting with Rietveld.
# Please keep the list sorted.
Alain Vongsouvanhalainv <alainv@google.com>
Andrew Gerrand <adg@golang.org>
Brad Fitzpatrick <bradfitz@golang.org>
Francesc Campoy <campoy@golang.org>
Garrick Evans <garrick@google.com>
Glenn Lewis <gmlewis@google.com>
Ivan Krasin <krasin@golang.org>
Jason Hall <jasonhall@google.com>
Johan Euphrosine <proppy@google.com>
Kostik Shtoyk <kostik@google.com>
Nick Craig-Wood <nickcw@gmail.com>
Scott Van Woudenberg <scottvw@google.com>
Takashi Matsuo <tmatsuo@google.com>

View File

@ -0,0 +1,27 @@
Copyright (c) 2011 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,9 @@
all:
go install code.google.com/p/google-api-go-client/googleapi
go install code.google.com/p/google-api-go-client/google-api-go-generator
$(GOPATH)/bin/google-api-go-generator -cache=false -install -api=*
cached:
go install code.google.com/p/google-api-go-client/googleapi
go install code.google.com/p/google-api-go-client/google-api-go-generator
$(GOPATH)/bin/google-api-go-generator -cache=true -install -api=*

View File

@ -0,0 +1,13 @@
Discovery Service:
http://code.google.com/apis/discovery/
http://code.google.com/apis/discovery/v1/reference.html
The "type" key:
http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1
The "format" key:
http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23
http://code.google.com/apis/discovery/v1/reference.html#parameter-format-summary
Google JSON format docs:
http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.xml

View File

@ -0,0 +1,10 @@
Most of this project is auto-generated.
The notable directories which are not auto-generated:
google-api-go-generator/ -- the generator itself
google-api/ -- shared common code, used by auto-generated code
examples/ -- sample code
When changing the generator, re-compile all APIs and submit the
modified APIs in the same CL as the generator changes itself.

View File

@ -0,0 +1,2 @@
Moved to:
http://code.google.com/p/google-api-go-client/issues/

View File

@ -1,18 +1,18 @@
{
"kind": "discovery#restDescription",
"etag": "\"FrPV2U6xXFUq8eRv_PO3IoAURkc/Qrs2SriggaSYO28pp7DFm8wFPbo\"",
"etag": "\"l66ggWbucbkBw9Lpos72oziyefE/qp3DHGvWPpREzEdWk7WwxnpgC9w\"",
"discoveryVersion": "v1",
"id": "compute:v1",
"name": "compute",
"version": "v1",
"revision": "20140625",
"revision": "20141014",
"title": "Compute Engine API",
"description": "API for the Google Compute Engine service.",
"ownerDomain": "google.com",
"ownerName": "Google",
"icons": {
"x16": "http://www.google.com/images/icons/product/compute_engine-16.png",
"x32": "http://www.google.com/images/icons/product/compute_engine-32.png"
"x16": "https://www.google.com/images/icons/product/compute_engine-16.png",
"x32": "https://www.google.com/images/icons/product/compute_engine-32.png"
},
"documentationLink": "https://developers.google.com/compute/docs/reference/latest/",
"protocol": "rest",
@ -345,6 +345,17 @@
"$ref": "AttachedDiskInitializeParams",
"description": "Initialization parameters."
},
"interface": {
"type": "string",
"enum": [
"NVME",
"SCSI"
],
"enumDescriptions": [
"",
""
]
},
"kind": {
"type": "string",
"description": "Type of the resource.",
@ -395,7 +406,7 @@
"AttachedDiskInitializeParams": {
"id": "AttachedDiskInitializeParams",
"type": "object",
"description": "Initialization parameters for the new disk (Mutually exclusive with 'source', can currently only be specified on the boot disk).",
"description": "Initialization parameters for the new disk (input-only). Can only be specified on the boot disk or local SSDs. Mutually exclusive with 'source'.",
"properties": {
"diskName": {
"type": "string",
@ -444,7 +455,7 @@
},
"group": {
"type": "string",
"description": "URL of a zonal Cloud Resource View resource. This resoure view defines the list of instances that serve traffic. Member virtual machine instances from each resource view must live in the same zone as the resource view itself."
"description": "URL of a zonal Cloud Resource View resource. This resource view defines the list of instances that serve traffic. Member virtual machine instances from each resource view must live in the same zone as the resource view itself. No two backends in a backend service are allowed to use same Resource View resource."
},
"maxRate": {
"type": "integer",
@ -512,9 +523,13 @@
},
"port": {
"type": "integer",
"description": "The TCP port to connect on the backend. The default value is 80.",
"description": "Deprecated in favor of port_name. The TCP port to connect on the backend. The default value is 80.",
"format": "int32"
},
"portName": {
"type": "string",
"description": "Name of backend port. The same name should appear in the resource views referenced by this service. Required."
},
"protocol": {
"type": "string",
"enum": [
@ -675,7 +690,7 @@
},
"sourceImage": {
"type": "string",
"description": "The source image used to create this disk. Once the source image has been deleted from the system, this field will not be set, even if an image with the same name has been re-created."
"description": "The source image used to create this disk."
},
"sourceImageId": {
"type": "string",
@ -683,7 +698,7 @@
},
"sourceSnapshot": {
"type": "string",
"description": "The source snapshot used to create this disk. Once the source snapshot has been deleted from the system, this field will be cleared, and will not be set even if a snapshot with the same name has been re-created."
"description": "The source snapshot used to create this disk."
},
"sourceSnapshotId": {
"type": "string",
@ -786,6 +801,11 @@
"type": "string",
"description": "Creation timestamp in RFC3339 text format (output only)."
},
"defaultDiskSizeGb": {
"type": "string",
"description": "Server defined default disk size in gb (output only).",
"format": "int64"
},
"deprecated": {
"$ref": "DeprecationStatus",
"description": "The deprecation status associated with this disk type."
@ -1085,13 +1105,7 @@
},
"network": {
"type": "string",
"description": "URL of the network to which this firewall is applied; provided by the client when the firewall is created.",
"annotations": {
"required": [
"compute.firewalls.insert",
"compute.firewalls.patch"
]
}
"description": "URL of the network to which this firewall is applied; provided by the client when the firewall is created."
},
"selfLink": {
"type": "string",
@ -1162,7 +1176,7 @@
},
"IPProtocol": {
"type": "string",
"description": "The IP protocol to which this rule applies, valid options are 'TCP', 'UDP', 'ESP', 'AH' or 'SCTP'",
"description": "The IP protocol to which this rule applies, valid options are 'TCP', 'UDP', 'ESP', 'AH' or 'SCTP'.",
"enum": [
"AH",
"ESP",
@ -1203,7 +1217,7 @@
},
"portRange": {
"type": "string",
"description": "Applicable only when 'IPProtocol' is 'TCP', 'UDP' or 'SCTP', only packets addressed to ports in the specified range will be forwarded to 'target'. If 'portRange' is left empty (default value), all ports are forwarded. Forwarding rules with the same [IPAddress, IPProtocol] pair must have disjoint port ranges. @pattern: \\d+(?:-\\d+)?"
"description": "Applicable only when 'IPProtocol' is 'TCP', 'UDP' or 'SCTP', only packets addressed to ports in the specified range will be forwarded to 'target'. If 'portRange' is left empty (default value), all ports are forwarded. Forwarding rules with the same [IPAddress, IPProtocol] pair must have disjoint port ranges."
},
"region": {
"type": "string",
@ -1385,6 +1399,11 @@
"ipAddress": {
"type": "string",
"description": "The IP address represented by this resource."
},
"port": {
"type": "integer",
"description": "The port on the instance.",
"format": "int32"
}
}
},
@ -1398,7 +1417,7 @@
},
"hosts": {
"type": "array",
"description": "The list of host patterns to match. They must be FQDN except that it may start with ?*.? or ?*-?. The ?*? acts like a glob and will match any string of atoms (separated by .?s and -?s) to the left.",
"description": "The list of host patterns to match. They must be valid hostnames except that they may start with *. or *-. The * acts like a glob and will match any string of atoms (separated by .s and -s) to the left.",
"items": {
"type": "string"
}
@ -1597,7 +1616,7 @@
},
"sourceDisk": {
"type": "string",
"description": "The source disk used to create this image. Once the source disk has been deleted from the system, this field will be cleared, and will not be set even if a disk with the same name has been re-created."
"description": "The source disk used to create this image."
},
"sourceDiskId": {
"type": "string",
@ -1836,6 +1855,63 @@
}
}
},
"InstanceProperties": {
"id": "InstanceProperties",
"type": "object",
"description": "",
"properties": {
"canIpForward": {
"type": "boolean",
"description": "Allows instances created based on this template to send packets with source IP addresses other than their own and receive packets with destination IP addresses other than their own. If these instances will be used as an IP gateway or it will be set as the next-hop in a Route resource, say true. If unsure, leave this set to false."
},
"description": {
"type": "string",
"description": "An optional textual description for the instances created based on the instance template resource; provided by the client when the template is created."
},
"disks": {
"type": "array",
"description": "Array of disks associated with instance created based on this template.",
"items": {
"$ref": "AttachedDisk"
}
},
"machineType": {
"type": "string",
"description": "Name of the machine type resource describing which machine type to use to host the instances created based on this template; provided by the client when the instance template is created.",
"annotations": {
"required": [
"compute.instanceTemplates.insert"
]
}
},
"metadata": {
"$ref": "Metadata",
"description": "Metadata key/value pairs assigned to instances created based on this template. Consists of custom metadata or predefined keys; see Instance documentation for more information."
},
"networkInterfaces": {
"type": "array",
"description": "Array of configurations for this interface. This specifies how this interface is configured to interact with other network services, such as connecting to the internet. Currently, ONE_TO_ONE_NAT is the only access config supported. If there are no accessConfigs specified, then this instances created based based on this template will have no external internet access.",
"items": {
"$ref": "NetworkInterface"
}
},
"scheduling": {
"$ref": "Scheduling",
"description": "Scheduling options for the instances created based on this template."
},
"serviceAccounts": {
"type": "array",
"description": "A list of service accounts each with specified scopes, for which access tokens are to be made available to the instances created based on this template, through metadata queries.",
"items": {
"$ref": "ServiceAccount"
}
},
"tags": {
"$ref": "Tags",
"description": "A list of tags to be applied to the instances created based on this template used to identify valid sources or targets for network firewalls. Provided by the client on instance creation. The tags can be later modified by the setTags method. Each tag within the list must comply with RFC1035."
}
}
},
"InstanceReference": {
"id": "InstanceReference",
"type": "object",
@ -1845,6 +1921,80 @@
}
}
},
"InstanceTemplate": {
"id": "InstanceTemplate",
"type": "object",
"description": "An Instance Template resource.",
"properties": {
"creationTimestamp": {
"type": "string",
"description": "Creation timestamp in RFC3339 text format (output only)."
},
"description": {
"type": "string",
"description": "An optional textual description of the instance template resource; provided by the client when the resource is created."
},
"id": {
"type": "string",
"description": "Unique identifier for the resource; defined by the server (output only).",
"format": "uint64"
},
"kind": {
"type": "string",
"description": "Type of the resource.",
"default": "compute#instanceTemplate"
},
"name": {
"type": "string",
"description": "Name of the instance template resource; provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035",
"pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?",
"annotations": {
"required": [
"compute.instanceTemplates.insert"
]
}
},
"properties": {
"$ref": "InstanceProperties",
"description": "The instance properties portion of this instance template resource."
},
"selfLink": {
"type": "string",
"description": "Server defined URL for the resource (output only)."
}
}
},
"InstanceTemplateList": {
"id": "InstanceTemplateList",
"type": "object",
"description": "Contains a list of instance template resources.",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the resource; defined by the server (output only)."
},
"items": {
"type": "array",
"description": "A list of instance template resources.",
"items": {
"$ref": "InstanceTemplate"
}
},
"kind": {
"type": "string",
"description": "Type of resource.",
"default": "compute#instanceTemplateList"
},
"nextPageToken": {
"type": "string",
"description": "A token used to continue a truncated list request (output only)."
},
"selfLink": {
"type": "string",
"description": "Server defined URL for this resource (output only)."
}
}
},
"InstancesScopedList": {
"id": "InstancesScopedList",
"type": "object",
@ -1922,9 +2072,13 @@
"type": "object",
"description": "A license resource.",
"properties": {
"chargesUseFee": {
"type": "boolean",
"description": "If true, the customer will be charged license fee for running software that contains this license on an instance."
},
"kind": {
"type": "string",
"description": "Identifies what kind of resource this is. Value: the fixed string \"compute#license\".",
"description": "Type of resource.",
"default": "compute#license"
},
"name": {
@ -2678,7 +2832,7 @@
"properties": {
"paths": {
"type": "array",
"description": "The list of path patterns to match. Each must start with ?/\" and the only place a \"*\" is allowed is at the end following a \"/\". The string fed to the path matcher does not include any text after the first \"?\" or \"#\", and those chars are not allowed here.",
"description": "The list of path patterns to match. Each must start with / and the only place a * is allowed is at the end following a /. The string fed to the path matcher does not include any text after the first ? or #, and those chars are not allowed here.",
"items": {
"type": "string"
}
@ -2765,6 +2919,7 @@
"IN_USE_ADDRESSES",
"KERNELS",
"KERNELS_TOTAL_GB",
"LOCAL_SSD_TOTAL_GB",
"NETWORKS",
"OPERATIONS",
"ROUTES",
@ -2800,6 +2955,7 @@
"",
"",
"",
"",
""
]
},
@ -2909,7 +3065,8 @@
"type": "object",
"properties": {
"group": {
"type": "string"
"type": "string",
"description": "A URI referencing one of the resource views listed in the backend service."
}
}
},
@ -3208,7 +3365,7 @@
},
"sourceDisk": {
"type": "string",
"description": "The source disk used to create this snapshot. Once the source disk has been deleted from the system, this field will be cleared, and will not be set even if a disk with the same name has been re-created (output only)."
"description": "The source disk used to create this snapshot."
},
"sourceDiskId": {
"type": "string",
@ -6351,6 +6508,146 @@
}
}
},
"instanceTemplates": {
"methods": {
"delete": {
"id": "compute.instanceTemplates.delete",
"path": "{project}/global/instanceTemplates/{instanceTemplate}",
"httpMethod": "DELETE",
"description": "Deletes the specified instance template resource.",
"parameters": {
"instanceTemplate": {
"type": "string",
"description": "Name of the instance template resource to delete.",
"required": true,
"pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?",
"location": "path"
},
"project": {
"type": "string",
"description": "Name of the project scoping this request.",
"required": true,
"pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?))",
"location": "path"
}
},
"parameterOrder": [
"project",
"instanceTemplate"
],
"response": {
"$ref": "Operation"
},
"scopes": [
"https://www.googleapis.com/auth/compute"
]
},
"get": {
"id": "compute.instanceTemplates.get",
"path": "{project}/global/instanceTemplates/{instanceTemplate}",
"httpMethod": "GET",
"description": "Returns the specified instance template resource.",
"parameters": {
"instanceTemplate": {
"type": "string",
"description": "Name of the instance template resource to return.",
"required": true,
"pattern": "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?",
"location": "path"
},
"project": {
"type": "string",
"description": "Name of the project scoping this request.",
"required": true,
"pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?))",
"location": "path"
}
},
"parameterOrder": [
"project",
"instanceTemplate"
],
"response": {
"$ref": "InstanceTemplate"
},
"scopes": [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/compute.readonly"
]
},
"insert": {
"id": "compute.instanceTemplates.insert",
"path": "{project}/global/instanceTemplates",
"httpMethod": "POST",
"description": "Creates an instance template resource in the specified project using the data included in the request.",
"parameters": {
"project": {
"type": "string",
"description": "Name of the project scoping this request.",
"required": true,
"pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?))",
"location": "path"
}
},
"parameterOrder": [
"project"
],
"request": {
"$ref": "InstanceTemplate"
},
"response": {
"$ref": "Operation"
},
"scopes": [
"https://www.googleapis.com/auth/compute"
]
},
"list": {
"id": "compute.instanceTemplates.list",
"path": "{project}/global/instanceTemplates",
"httpMethod": "GET",
"description": "Retrieves the list of instance template resources contained within the specified project.",
"parameters": {
"filter": {
"type": "string",
"description": "Optional. Filter expression for filtering listed resources.",
"location": "query"
},
"maxResults": {
"type": "integer",
"description": "Optional. Maximum count of results to be returned. Maximum value is 500 and default value is 500.",
"default": "500",
"format": "uint32",
"minimum": "0",
"maximum": "500",
"location": "query"
},
"pageToken": {
"type": "string",
"description": "Optional. Tag returned by a previous list request truncated by maxResults. Used to continue a previous list request.",
"location": "query"
},
"project": {
"type": "string",
"description": "Name of the project scoping this request.",
"required": true,
"pattern": "(?:(?:[-a-z0-9]{1,63}\\.)*(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?):)?(?:[0-9]{1,19}|(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?))",
"location": "path"
}
},
"parameterOrder": [
"project"
],
"response": {
"$ref": "InstanceTemplateList"
},
"scopes": [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/compute.readonly"
]
}
}
},
"instances": {
"methods": {
"addAccessConfig": {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,579 @@
{
"kind": "discovery#restDescription",
"etag": "\"l66ggWbucbkBw9Lpos72oziyefE/ZrZBeDfQYPqAxFURJt0IhCOLUHQ\"",
"discoveryVersion": "v1",
"id": "container:v1beta1",
"name": "container",
"version": "v1beta1",
"revision": "20141103",
"title": "Google Container Engine API",
"description": "The Google Container Engine API is used for building and managing container based applications, powered by the open source Kubernetes technology.",
"ownerDomain": "google.com",
"ownerName": "Google",
"icons": {
"x16": "http://www.google.com/images/icons/product/search-16.gif",
"x32": "http://www.google.com/images/icons/product/search-32.gif"
},
"protocol": "rest",
"baseUrl": "https://www.googleapis.com/container/v1beta1/projects/",
"basePath": "/container/v1beta1/projects/",
"rootUrl": "https://www.googleapis.com/",
"servicePath": "container/v1beta1/projects/",
"batchPath": "batch",
"parameters": {
"alt": {
"type": "string",
"description": "Data format for the response.",
"default": "json",
"enum": [
"json"
],
"enumDescriptions": [
"Responses with Content-Type of application/json"
],
"location": "query"
},
"fields": {
"type": "string",
"description": "Selector specifying which fields to include in a partial response.",
"location": "query"
},
"key": {
"type": "string",
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location": "query"
},
"oauth_token": {
"type": "string",
"description": "OAuth 2.0 token for the current user.",
"location": "query"
},
"prettyPrint": {
"type": "boolean",
"description": "Returns response with indentations and line breaks.",
"default": "true",
"location": "query"
},
"quotaUser": {
"type": "string",
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
"location": "query"
},
"userIp": {
"type": "string",
"description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
"location": "query"
}
},
"auth": {
"oauth2": {
"scopes": {
"https://www.googleapis.com/auth/cloud-platform": {
"description": "View and manage your data across Google Cloud Platform services"
}
}
}
},
"schemas": {
"Cluster": {
"id": "Cluster",
"type": "object",
"externalTypeName": "container.v1beta1.Cluster",
"properties": {
"clusterApiVersion": {
"type": "string",
"description": "The API version of the Kubernetes master and kubelets running in this cluster. Allowed value is 0.4.2, or leave blank to pick up the latest stable release."
},
"containerIpv4Cidr": {
"type": "string",
"description": "[Output only] The IP addresses of the container pods in this cluster, in CIDR notation (e.g. 1.2.3.4/29)."
},
"creationTimestamp": {
"type": "string",
"description": "[Output only] The time the cluster was created, in RFC3339 text format."
},
"description": {
"type": "string",
"description": "An optional description of this cluster."
},
"endpoint": {
"type": "string",
"description": "[Output only] The IP address of this cluster's Kubernetes master. The endpoint can be accessed from the internet at https://username:password@endpoint/.\n\nSee the masterAuth property of this resource for username and password information."
},
"masterAuth": {
"$ref": "MasterAuth",
"description": "The HTTP basic authentication information for accessing the master. Because the master endpoint is open to the internet, you should create a strong password."
},
"name": {
"type": "string",
"description": "The name of this cluster. The name must be unique within this project and zone, and can be up to 40 characters with the following restrictions: \n- Lowercase letters, numbers, and hyphens only.\n- Must start with a letter.\n- Must end with a number or a letter."
},
"nodeConfig": {
"$ref": "NodeConfig",
"description": "The machine type and image to use for all nodes in this cluster. See the descriptions of the child properties of nodeConfig."
},
"nodeRoutingPrefixSize": {
"type": "integer",
"description": "[Output only] The size of the address space on each node for hosting containers.",
"format": "int32"
},
"numNodes": {
"type": "integer",
"description": "The number of nodes to create in this cluster. You must ensure that your Compute Engine resource quota is sufficient for this number of instances plus one (to include the master). You must also have available firewall and routes quota.",
"format": "int32"
},
"servicesIpv4Cidr": {
"type": "string",
"description": "[Output only] The IP addresses of the Kubernetes services in this cluster, in CIDR notation (e.g. 1.2.3.4/29). Service addresses are always in the 10.0.0.0/16 range."
},
"status": {
"type": "string",
"description": "[Output only] The current status of this cluster.",
"enum": [
"error",
"provisioning",
"running",
"stopping"
],
"enumDescriptions": [
"",
"",
"",
""
]
},
"statusMessage": {
"type": "string",
"description": "[Output only] Additional information about the current status of this cluster, if available."
},
"zone": {
"type": "string",
"description": "[Output only] The name of the Google Compute Engine zone in which the cluster resides."
}
}
},
"CreateClusterRequest": {
"id": "CreateClusterRequest",
"type": "object",
"externalTypeName": "container.v1beta1.CreateClusterRequest",
"properties": {
"cluster": {
"$ref": "Cluster",
"description": "A cluster resource."
}
}
},
"ListAggregatedClustersResponse": {
"id": "ListAggregatedClustersResponse",
"type": "object",
"externalTypeName": "container.v1beta1.ListAggregatedClustersResponse",
"properties": {
"clusters": {
"type": "array",
"description": "A list of clusters in the project, across all zones.",
"items": {
"$ref": "Cluster"
}
}
}
},
"ListAggregatedOperationsResponse": {
"id": "ListAggregatedOperationsResponse",
"type": "object",
"externalTypeName": "container.v1beta1.ListAggregatedOperationsResponse",
"properties": {
"operations": {
"type": "array",
"description": "A list of operations in the project, across all zones.",
"items": {
"$ref": "Operation"
}
}
}
},
"ListClustersResponse": {
"id": "ListClustersResponse",
"type": "object",
"externalTypeName": "container.v1beta1.ListClustersResponse",
"properties": {
"clusters": {
"type": "array",
"description": "A list of clusters in the project in the specified zone.",
"items": {
"$ref": "Cluster"
}
}
}
},
"ListOperationsResponse": {
"id": "ListOperationsResponse",
"type": "object",
"externalTypeName": "container.v1beta1.ListOperationsResponse",
"properties": {
"operations": {
"type": "array",
"description": "A list of operations in the project in the specified zone.",
"items": {
"$ref": "Operation"
}
}
}
},
"MasterAuth": {
"id": "MasterAuth",
"type": "object",
"externalTypeName": "container.v1beta1.MasterAuth",
"properties": {
"password": {
"type": "string",
"description": "The password to use when accessing the Kubernetes master endpoint."
},
"user": {
"type": "string",
"description": "The username to use when accessing the Kubernetes master endpoint."
}
}
},
"NodeConfig": {
"id": "NodeConfig",
"type": "object",
"externalTypeName": "container.v1beta1.NodeConfig",
"properties": {
"machineType": {
"type": "string",
"description": "The name of a Google Compute Engine machine type (e.g. n1-standard-1).\n\nIf unspecified, the default machine type is n1-standard-1."
},
"sourceImage": {
"type": "string",
"description": "The fully-specified name of a Google Compute Engine image. For example: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/backports-debian-7-wheezy-vYYYYMMDD (where YYYMMDD is the version date).\n\nIf specifying an image, you are responsible for ensuring its compatibility with the Debian 7 backports image. We recommend leaving this field blank to accept the default backports-debian-7-wheezy value."
}
}
},
"Operation": {
"id": "Operation",
"type": "object",
"description": "Defines the operation resource. All fields are output only.",
"externalTypeName": "container.v1beta1.Operation",
"properties": {
"errorMessage": {
"type": "string",
"description": "If an error has occurred, a textual description of the error."
},
"name": {
"type": "string",
"description": "The server-assigned ID for this operation. If the operation is fulfilled upfront, it may not have a resource name."
},
"operationType": {
"type": "string",
"description": "The operation type.",
"enum": [
"createCluster",
"deleteCluster"
],
"enumDescriptions": [
"",
""
]
},
"status": {
"type": "string",
"description": "The current status of the operation.",
"enum": [
"done",
"pending",
"running"
],
"enumDescriptions": [
"",
"",
""
]
},
"target": {
"type": "string",
"description": "[Optional] The URL of the cluster resource that this operation is associated with."
},
"zone": {
"type": "string",
"description": "The name of the Google Compute Engine zone in which the operation is taking place."
}
}
}
},
"resources": {
"projects": {
"resources": {
"clusters": {
"methods": {
"list": {
"id": "container.projects.clusters.list",
"path": "{projectId}/clusters",
"httpMethod": "GET",
"description": "Lists all clusters owned by a project across all zones.",
"parameters": {
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId"
],
"response": {
"$ref": "ListAggregatedClustersResponse"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
},
"operations": {
"methods": {
"list": {
"id": "container.projects.operations.list",
"path": "{projectId}/operations",
"httpMethod": "GET",
"description": "Lists all operations in a project, across all zones.",
"parameters": {
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId"
],
"response": {
"$ref": "ListAggregatedOperationsResponse"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
},
"zones": {
"resources": {
"clusters": {
"methods": {
"create": {
"id": "container.projects.zones.clusters.create",
"path": "{projectId}/zones/{zoneId}/clusters",
"httpMethod": "POST",
"description": "Creates a cluster, consisting of the specified number and type of Google Compute Engine instances, plus a Kubernetes master instance.\n\nThe cluster is created in the project's default network.\n\nA firewall is added that allows traffic into port 443 on the master, which enables HTTPS. A firewall and a route is added for each node to allow the containers on that node to communicate with all other instances in the cluster.\n\nFinally, a route named k8s-iproute-10-xx-0-0 is created to track that the cluster's 10.xx.0.0/16 CIDR has been assigned.",
"parameters": {
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
},
"zoneId": {
"type": "string",
"description": "The name of the Google Compute Engine zone in which the cluster resides.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId",
"zoneId"
],
"request": {
"$ref": "CreateClusterRequest"
},
"response": {
"$ref": "Operation"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
},
"delete": {
"id": "container.projects.zones.clusters.delete",
"path": "{projectId}/zones/{zoneId}/clusters/{clusterId}",
"httpMethod": "DELETE",
"description": "Deletes the cluster, including the Kubernetes master and all worker nodes.\n\nFirewalls and routes that were configured at cluster creation are also deleted.",
"parameters": {
"clusterId": {
"type": "string",
"description": "The name of the cluster to delete.",
"required": true,
"location": "path"
},
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
},
"zoneId": {
"type": "string",
"description": "The name of the Google Compute Engine zone in which the cluster resides.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId",
"zoneId",
"clusterId"
],
"response": {
"$ref": "Operation"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
},
"get": {
"id": "container.projects.zones.clusters.get",
"path": "{projectId}/zones/{zoneId}/clusters/{clusterId}",
"httpMethod": "GET",
"description": "Gets a specific cluster.",
"parameters": {
"clusterId": {
"type": "string",
"description": "The name of the cluster to retrieve.",
"required": true,
"location": "path"
},
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
},
"zoneId": {
"type": "string",
"description": "The name of the Google Compute Engine zone in which the cluster resides.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId",
"zoneId",
"clusterId"
],
"response": {
"$ref": "Cluster"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
},
"list": {
"id": "container.projects.zones.clusters.list",
"path": "{projectId}/zones/{zoneId}/clusters",
"httpMethod": "GET",
"description": "Lists all clusters owned by a project in the specified zone.",
"parameters": {
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
},
"zoneId": {
"type": "string",
"description": "The name of the Google Compute Engine zone in which the cluster resides.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId",
"zoneId"
],
"response": {
"$ref": "ListClustersResponse"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
},
"operations": {
"methods": {
"get": {
"id": "container.projects.zones.operations.get",
"path": "{projectId}/zones/{zoneId}/operations/{operationId}",
"httpMethod": "GET",
"description": "Gets the specified operation.",
"parameters": {
"operationId": {
"type": "string",
"description": "The server-assigned name of the operation.",
"required": true,
"location": "path"
},
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
},
"zoneId": {
"type": "string",
"description": "The name of the Google Compute Engine zone in which the operation resides. This is always the same zone as the cluster with which the operation is associated.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId",
"zoneId",
"operationId"
],
"response": {
"$ref": "Operation"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
},
"list": {
"id": "container.projects.zones.operations.list",
"path": "{projectId}/zones/{zoneId}/operations",
"httpMethod": "GET",
"description": "Lists all operations in a project in a specific zone.",
"parameters": {
"projectId": {
"type": "string",
"description": "The Google Developers Console project ID or project number.",
"required": true,
"location": "path"
},
"zoneId": {
"type": "string",
"description": "The name of the Google Compute Engine zone to return operations for.",
"required": true,
"location": "path"
}
},
"parameterOrder": [
"projectId",
"zoneId"
],
"response": {
"$ref": "ListOperationsResponse"
},
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
}
}
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -17,8 +17,9 @@ import (
"net/textproto"
"net/url"
"os"
"regexp"
"strings"
"code.google.com/p/google-api-go-client/googleapi/internal/uritemplates"
)
// ContentTyper is an interface for Readers which know (or would like
@ -310,27 +311,16 @@ func SetOpaque(u *url.URL) {
}
}
// Find {encoded} strings
var findEncodedStrings = regexp.MustCompile(`(\{[A-Za-z_]+\})`)
// Expand subsitutes any {encoded} strings in the URL passed in using
// the map supplied.
//
// This calls SetOpaque to avoid encoding of the parameters in the URL path.
func Expand(u *url.URL, expansions map[string]string) {
u.Path = findEncodedStrings.ReplaceAllStringFunc(u.Path, func(replace string) string {
argument := replace[1 : len(replace)-1]
value, ok := expansions[argument]
if !ok {
// Expansion not found - leave unchanged
return replace
}
// Would like to call url.escape(value, encodePath) here
encodedValue := url.QueryEscape(value)
encodedValue = strings.Replace(encodedValue, "+", "%20", -1)
return encodedValue
})
SetOpaque(u)
expanded, err := uritemplates.Expand(u.Path, expansions)
if err == nil {
u.Path = expanded
SetOpaque(u)
}
}
// CloseBody is used to close res.Body.
@ -375,3 +365,37 @@ func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
}
return json.Unmarshal(buf.Bytes(), dst) == nil
}
// A Field names a field to be retrieved with a partial response.
// See https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
//
// Partial responses can dramatically reduce the amount of data that must be sent to your application.
// In order to request partial responses, you can specify the full list of fields
// that your application needs by adding the Fields option to your request.
//
// Field strings use camelCase with leading lower-case characters to identify fields within the response.
//
// For example, if your response has a "NextPageToken" and a slice of "Items" with "Id" fields,
// you could request just those fields like this:
//
// svc.Events.List().Fields("nextPageToken", "items/id").Do()
//
// or if you were also interested in each Item's "Updated" field, you can combine them like this:
//
// svc.Events.List().Fields("nextPageToken", "items(id,updated)").Do()
//
// More information about field formatting can be found here:
// https://developers.google.com/+/api/#fields-syntax
//
// Another way to find field names is through the Google API explorer:
// https://developers.google.com/apis-explorer/#p/
type Field string
// CombineFields combines fields into a single string.
func CombineFields(s []Field) string {
r := make([]string, len(s))
for i, v := range s {
r[i] = string(v)
}
return strings.Join(r, ",")
}

View File

@ -146,7 +146,7 @@ var expandTests = []ExpandTest{
map[string]string{
"bucket": "red or blue",
},
"http://www.golang.org/{object}/delete",
"http://www.golang.org//delete",
},
// multiple expansions
{
@ -182,6 +182,16 @@ var expandTests = []ExpandTest{
},
"http://www.golang.org/{bucket/get",
},
// "+" prefix for suppressing escape
// See also: http://tools.ietf.org/html/rfc6570#section-3.2.3
{
"http://www.golang.org/{+topic}",
map[string]string{
"topic": "/topics/myproject/mytopic",
},
// The double slashes here look weird, but it's intentional
"http://www.golang.org//topics/myproject/mytopic",
},
}
func TestExpand(t *testing.T) {

View File

@ -0,0 +1,18 @@
Copyright (c) 2013 Joshua Tacoma
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,359 @@
// Copyright 2013 Joshua Tacoma. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package uritemplates is a level 4 implementation of RFC 6570 (URI
// Template, http://tools.ietf.org/html/rfc6570).
//
// To use uritemplates, parse a template string and expand it with a value
// map:
//
// template, _ := uritemplates.Parse("https://api.github.com/repos{/user,repo}")
// values := make(map[string]interface{})
// values["user"] = "jtacoma"
// values["repo"] = "uritemplates"
// expanded, _ := template.ExpandString(values)
// fmt.Printf(expanded)
//
package uritemplates
import (
"bytes"
"errors"
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
)
var (
unreserved = regexp.MustCompile("[^A-Za-z0-9\\-._~]")
reserved = regexp.MustCompile("[^A-Za-z0-9\\-._~:/?#[\\]@!$&'()*+,;=]")
validname = regexp.MustCompile("^([A-Za-z0-9_\\.]|%[0-9A-Fa-f][0-9A-Fa-f])+$")
hex = []byte("0123456789ABCDEF")
)
func pctEncode(src []byte) []byte {
dst := make([]byte, len(src)*3)
for i, b := range src {
buf := dst[i*3 : i*3+3]
buf[0] = 0x25
buf[1] = hex[b/16]
buf[2] = hex[b%16]
}
return dst
}
func escape(s string, allowReserved bool) (escaped string) {
if allowReserved {
escaped = string(reserved.ReplaceAllFunc([]byte(s), pctEncode))
} else {
escaped = string(unreserved.ReplaceAllFunc([]byte(s), pctEncode))
}
return escaped
}
// A UriTemplate is a parsed representation of a URI template.
type UriTemplate struct {
raw string
parts []templatePart
}
// Parse parses a URI template string into a UriTemplate object.
func Parse(rawtemplate string) (template *UriTemplate, err error) {
template = new(UriTemplate)
template.raw = rawtemplate
split := strings.Split(rawtemplate, "{")
template.parts = make([]templatePart, len(split)*2-1)
for i, s := range split {
if i == 0 {
if strings.Contains(s, "}") {
err = errors.New("unexpected }")
break
}
template.parts[i].raw = s
} else {
subsplit := strings.Split(s, "}")
if len(subsplit) != 2 {
err = errors.New("malformed template")
break
}
expression := subsplit[0]
template.parts[i*2-1], err = parseExpression(expression)
if err != nil {
break
}
template.parts[i*2].raw = subsplit[1]
}
}
if err != nil {
template = nil
}
return template, err
}
type templatePart struct {
raw string
terms []templateTerm
first string
sep string
named bool
ifemp string
allowReserved bool
}
type templateTerm struct {
name string
explode bool
truncate int
}
func parseExpression(expression string) (result templatePart, err error) {
switch expression[0] {
case '+':
result.sep = ","
result.allowReserved = true
expression = expression[1:]
case '.':
result.first = "."
result.sep = "."
expression = expression[1:]
case '/':
result.first = "/"
result.sep = "/"
expression = expression[1:]
case ';':
result.first = ";"
result.sep = ";"
result.named = true
expression = expression[1:]
case '?':
result.first = "?"
result.sep = "&"
result.named = true
result.ifemp = "="
expression = expression[1:]
case '&':
result.first = "&"
result.sep = "&"
result.named = true
result.ifemp = "="
expression = expression[1:]
case '#':
result.first = "#"
result.sep = ","
result.allowReserved = true
expression = expression[1:]
default:
result.sep = ","
}
rawterms := strings.Split(expression, ",")
result.terms = make([]templateTerm, len(rawterms))
for i, raw := range rawterms {
result.terms[i], err = parseTerm(raw)
if err != nil {
break
}
}
return result, err
}
func parseTerm(term string) (result templateTerm, err error) {
if strings.HasSuffix(term, "*") {
result.explode = true
term = term[:len(term)-1]
}
split := strings.Split(term, ":")
if len(split) == 1 {
result.name = term
} else if len(split) == 2 {
result.name = split[0]
var parsed int64
parsed, err = strconv.ParseInt(split[1], 10, 0)
result.truncate = int(parsed)
} else {
err = errors.New("multiple colons in same term")
}
if !validname.MatchString(result.name) {
err = errors.New("not a valid name: " + result.name)
}
if result.explode && result.truncate > 0 {
err = errors.New("both explode and prefix modifers on same term")
}
return result, err
}
// Expand expands a URI template with a set of values to produce a string.
func (self *UriTemplate) Expand(value interface{}) (string, error) {
values, ismap := value.(map[string]interface{})
if !ismap {
if m, ismap := struct2map(value); !ismap {
return "", errors.New("expected map[string]interface{}, struct, or pointer to struct.")
} else {
return self.Expand(m)
}
}
var buf bytes.Buffer
for _, p := range self.parts {
err := p.expand(&buf, values)
if err != nil {
return "", err
}
}
return buf.String(), nil
}
func (self *templatePart) expand(buf *bytes.Buffer, values map[string]interface{}) error {
if len(self.raw) > 0 {
buf.WriteString(self.raw)
return nil
}
var zeroLen = buf.Len()
buf.WriteString(self.first)
var firstLen = buf.Len()
for _, term := range self.terms {
value, exists := values[term.name]
if !exists {
continue
}
if buf.Len() != firstLen {
buf.WriteString(self.sep)
}
switch v := value.(type) {
case string:
self.expandString(buf, term, v)
case []interface{}:
self.expandArray(buf, term, v)
case map[string]interface{}:
if term.truncate > 0 {
return errors.New("cannot truncate a map expansion")
}
self.expandMap(buf, term, v)
default:
if m, ismap := struct2map(value); ismap {
if term.truncate > 0 {
return errors.New("cannot truncate a map expansion")
}
self.expandMap(buf, term, m)
} else {
str := fmt.Sprintf("%v", value)
self.expandString(buf, term, str)
}
}
}
if buf.Len() == firstLen {
original := buf.Bytes()[:zeroLen]
buf.Reset()
buf.Write(original)
}
return nil
}
func (self *templatePart) expandName(buf *bytes.Buffer, name string, empty bool) {
if self.named {
buf.WriteString(name)
if empty {
buf.WriteString(self.ifemp)
} else {
buf.WriteString("=")
}
}
}
func (self *templatePart) expandString(buf *bytes.Buffer, t templateTerm, s string) {
if len(s) > t.truncate && t.truncate > 0 {
s = s[:t.truncate]
}
self.expandName(buf, t.name, len(s) == 0)
buf.WriteString(escape(s, self.allowReserved))
}
func (self *templatePart) expandArray(buf *bytes.Buffer, t templateTerm, a []interface{}) {
if len(a) == 0 {
return
} else if !t.explode {
self.expandName(buf, t.name, false)
}
for i, value := range a {
if t.explode && i > 0 {
buf.WriteString(self.sep)
} else if i > 0 {
buf.WriteString(",")
}
var s string
switch v := value.(type) {
case string:
s = v
default:
s = fmt.Sprintf("%v", v)
}
if len(s) > t.truncate && t.truncate > 0 {
s = s[:t.truncate]
}
if self.named && t.explode {
self.expandName(buf, t.name, len(s) == 0)
}
buf.WriteString(escape(s, self.allowReserved))
}
}
func (self *templatePart) expandMap(buf *bytes.Buffer, t templateTerm, m map[string]interface{}) {
if len(m) == 0 {
return
}
if !t.explode {
self.expandName(buf, t.name, len(m) == 0)
}
var firstLen = buf.Len()
for k, value := range m {
if firstLen != buf.Len() {
if t.explode {
buf.WriteString(self.sep)
} else {
buf.WriteString(",")
}
}
var s string
switch v := value.(type) {
case string:
s = v
default:
s = fmt.Sprintf("%v", v)
}
if t.explode {
buf.WriteString(escape(k, self.allowReserved))
buf.WriteRune('=')
buf.WriteString(escape(s, self.allowReserved))
} else {
buf.WriteString(escape(k, self.allowReserved))
buf.WriteRune(',')
buf.WriteString(escape(s, self.allowReserved))
}
}
}
func struct2map(v interface{}) (map[string]interface{}, bool) {
value := reflect.ValueOf(v)
switch value.Type().Kind() {
case reflect.Ptr:
return struct2map(value.Elem().Interface())
case reflect.Struct:
m := make(map[string]interface{})
for i := 0; i < value.NumField(); i++ {
tag := value.Type().Field(i).Tag
var name string
if strings.Contains(string(tag), ":") {
name = tag.Get("uri")
} else {
name = strings.TrimSpace(string(tag))
}
if len(name) == 0 {
name = value.Type().Field(i).Name
}
m[name] = value.Field(i).Interface()
}
return m, true
}
return nil, false
}

View File

@ -0,0 +1,13 @@
package uritemplates
func Expand(path string, expansions map[string]string) (string, error) {
template, err := Parse(path)
if err != nil {
return "", err
}
values := make(map[string]interface{})
for k, v := range expansions {
values[k] = v
}
return template.Expand(values)
}

View File

@ -45,7 +45,7 @@ kube::test::find_pkgs() {
# -covermode=atomic becomes default with -race in Go >=1.3
KUBE_COVER=${KUBE_COVER:--cover -covermode=atomic}
KUBE_TIMEOUT=${KUBE_TIMEOUT:--timeout 60s}
KUBE_TIMEOUT=${KUBE_TIMEOUT:--timeout 120s}
KUBE_RACE=${KUBE_RACE:--race}
kube::test::usage() {

View File

@ -32,6 +32,8 @@ type FakeCloud struct {
IP net.IP
Machines []string
NodeResources *api.NodeResources
ClusterList []string
MasterName string
cloudprovider.Zone
}
@ -45,6 +47,14 @@ func (f *FakeCloud) ClearCalls() {
f.Calls = []string{}
}
func (f *FakeCloud) ListClusters() ([]string, error) {
return f.ClusterList, f.Err
}
func (f *FakeCloud) Master(name string) (string, error) {
return f.MasterName, f.Err
}
func (f *FakeCloud) Clusters() (cloudprovider.Clusters, bool) {
return f, true
}