Remove mpagent, Machine Provider API clients

Bug: 897355
Change-Id: I805317fde3aa30b54f6aceb5cb7e30bd8cd4ca53
Reviewed-on: https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/1628180
Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>
Commit-Queue: smut <smut@google.com>
diff --git a/common/api/generate.go b/common/api/generate.go
index cf7a06c..bafec36 100644
--- a/common/api/generate.go
+++ b/common/api/generate.go
@@ -16,7 +16,6 @@
 //go:generate apigen -api-subproject "buildbucket" -service "https://cr-buildbucket.appspot.com" -api "buildbucket:v1" -api "swarmbucket:v1"
 //go:generate apigen -api-subproject "isolate" -service "https://isolateserver.appspot.com" -api "isolateservice:v1"
 //go:generate apigen -api-subproject "luci_config" -service "https://luci-config.appspot.com" -api "config:v1"
-//go:generate apigen -api-subproject "machine_provider" -service "https://machine-provider.appspot.com" -api "catalog:v1" -api "machine:v1"
 //go:generate apigen -api-subproject "swarming" -service "https://chromium-swarm.appspot.com" -api "swarming:v1"
 
 package api
diff --git a/common/api/machine_provider/catalog/v1/catalog-api.json b/common/api/machine_provider/catalog/v1/catalog-api.json
deleted file mode 100644
index e5cab8f..0000000
--- a/common/api/machine_provider/catalog/v1/catalog-api.json
+++ /dev/null
@@ -1,434 +0,0 @@
-{
-  "auth": {
-    "oauth2": {
-      "scopes": {
-        "https://www.googleapis.com/auth/userinfo.email": {
-          "description": "https://www.googleapis.com/auth/userinfo.email"
-        }
-      }
-    }
-  },
-  "basePath": "/_ah/api/catalog/v1",
-  "baseUrl": "https://machine-provider.appspot.com/_ah/api/catalog/v1",
-  "batchPath": "batch",
-  "description": "Implements cloud endpoints for the Machine Provider Catalog.",
-  "discoveryVersion": "v1",
-  "icons": {
-    "x16": "https://www.google.com/images/icons/product/search-16.gif",
-    "x32": "https://www.google.com/images/icons/product/search-32.gif"
-  },
-  "id": "catalog:v1",
-  "kind": "discovery#restDescription",
-  "methods": {
-    "add_machine": {
-      "description": "Handles an incoming CatalogMachineAdditionRequest.",
-      "httpMethod": "POST",
-      "id": "catalog.add_machine",
-      "path": "add_machine",
-      "request": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest",
-        "parameterName": "resource"
-      },
-      "response": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse"
-      },
-      "scopes": [
-        "https://www.googleapis.com/auth/userinfo.email"
-      ]
-    },
-    "add_machines": {
-      "description": "Handles an incoming CatalogMachineBatchAdditionRequest. Batches are intended to save on RPCs only. The batched requests will not execute transactionally.",
-      "httpMethod": "POST",
-      "id": "catalog.add_machines",
-      "path": "add_machines",
-      "request": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest",
-        "parameterName": "resource"
-      },
-      "response": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse"
-      },
-      "scopes": [
-        "https://www.googleapis.com/auth/userinfo.email"
-      ]
-    },
-    "delete_machine": {
-      "description": "Handles an incoming CatalogMachineDeletionRequest.",
-      "httpMethod": "POST",
-      "id": "catalog.delete_machine",
-      "path": "delete_machine",
-      "request": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest",
-        "parameterName": "resource"
-      },
-      "response": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse"
-      },
-      "scopes": [
-        "https://www.googleapis.com/auth/userinfo.email"
-      ]
-    },
-    "get": {
-      "description": "Handles an incoming CatalogMachineRetrievalRequest.",
-      "httpMethod": "POST",
-      "id": "catalog.get",
-      "path": "get",
-      "request": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest",
-        "parameterName": "resource"
-      },
-      "response": {
-        "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse"
-      },
-      "scopes": [
-        "https://www.googleapis.com/auth/userinfo.email"
-      ]
-    }
-  },
-  "name": "catalog",
-  "parameters": {
-    "alt": {
-      "default": "json",
-      "description": "Data format for the response.",
-      "enum": [
-        "json"
-      ],
-      "enumDescriptions": [
-        "Responses with Content-Type of application/json"
-      ],
-      "location": "query",
-      "type": "string"
-    },
-    "fields": {
-      "description": "Selector specifying which fields to include in a partial response.",
-      "location": "query",
-      "type": "string"
-    },
-    "key": {
-      "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",
-      "type": "string"
-    },
-    "oauth_token": {
-      "description": "OAuth 2.0 token for the current user.",
-      "location": "query",
-      "type": "string"
-    },
-    "prettyPrint": {
-      "default": "true",
-      "description": "Returns response with indentations and line breaks.",
-      "location": "query",
-      "type": "boolean"
-    },
-    "quotaUser": {
-      "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",
-      "type": "string"
-    },
-    "userIp": {
-      "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
-      "location": "query",
-      "type": "string"
-    }
-  },
-  "protocol": "rest",
-  "rootUrl": "https://machine-provider.appspot.com/_ah/api/",
-  "schemas": {
-    "ComponentsMachineProviderDimensionsDimensions": {
-      "description": "Represents the dimensions of a machine.",
-      "id": "ComponentsMachineProviderDimensionsDimensions",
-      "properties": {
-        "backend": {
-          "enum": [
-            "DUMMY",
-            "GCE",
-            "VSPHERE"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "disk_gb": {
-          "format": "int64",
-          "type": "string"
-        },
-        "disk_type": {
-          "enum": [
-            "HDD",
-            "SSD"
-          ],
-          "enumDescriptions": [
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "hostname": {
-          "type": "string"
-        },
-        "linux_flavor": {
-          "enum": [
-            "DEBIAN",
-            "UBUNTU"
-          ],
-          "enumDescriptions": [
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "memory_gb": {
-          "format": "double",
-          "type": "number"
-        },
-        "num_cpus": {
-          "format": "int64",
-          "type": "string"
-        },
-        "os_family": {
-          "enum": [
-            "LINUX",
-            "OSX",
-            "WINDOWS"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "os_version": {
-          "type": "string"
-        },
-        "project": {
-          "type": "string"
-        },
-        "snapshot": {
-          "type": "string"
-        },
-        "snapshot_labels": {
-          "items": {
-            "type": "string"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderPoliciesKeyValuePair": {
-      "description": "Represents a key-value pair.",
-      "id": "ComponentsMachineProviderPoliciesKeyValuePair",
-      "properties": {
-        "key": {
-          "required": true,
-          "type": "string"
-        },
-        "value": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderPoliciesPolicies": {
-      "description": "Represents the policies for a machine. There are two Pub/Sub channels of communication for each machine. One is the backend-level channel which the Machine Provider will use to tell the backend that the machine has been leased, or that the machine needs to be reclaimed. The other is the channel between the Machine Provider and the machine itself. The machine should listen for instructions from the Machine Provider on this channel. Since the machine itself is what's being leased out to untrusted users, we will assign this Cloud Pub/Sub topic and give it restricted permissions which only allow it to subscribe to the one topic. On the other hand, the backend is trusted so we allow it to choose its own topic. When a backend adds a machine to the Catalog, it should provide the Pub/Sub topic and project to communicate on regarding the machine, as well as the service account on the machine itself which will be used to authenticate pull requests on the subscription created by the Machine Provider for the machine.",
-      "id": "ComponentsMachineProviderPoliciesPolicies",
-      "properties": {
-        "backend_attributes": {
-          "description": "Represents a key-value pair.",
-          "items": {
-            "$ref": "ComponentsMachineProviderPoliciesKeyValuePair"
-          },
-          "type": "array"
-        },
-        "backend_project": {
-          "type": "string"
-        },
-        "backend_topic": {
-          "type": "string"
-        },
-        "machine_service_account": {
-          "type": "string"
-        },
-        "on_reclamation": {
-          "default": "MAKE_AVAILABLE",
-          "enum": [
-            "DELETE",
-            "MAKE_AVAILABLE",
-            "RECLAIM"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse": {
-      "description": "Represents a response to a batched catalog manipulation request.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse",
-      "properties": {
-        "responses": {
-          "description": "Represents a response to a catalog manipulation request.",
-          "items": {
-            "$ref": "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest": {
-      "description": "Represents a request to add a machine to the catalog. dimensions.backend must be specified. dimensions.hostname must be unique per backend.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest",
-      "properties": {
-        "dimensions": {
-          "$ref": "ComponentsMachineProviderDimensionsDimensions",
-          "description": "Represents the dimensions of a machine.",
-          "required": true
-        },
-        "policies": {
-          "$ref": "ComponentsMachineProviderPoliciesPolicies",
-          "description": "Represents the policies for a machine. There are two Pub/Sub channels of communication for each machine. One is the backend-level channel which the Machine Provider will use to tell the backend that the machine has been leased, or that the machine needs to be reclaimed. The other is the channel between the Machine Provider and the machine itself. The machine should listen for instructions from the Machine Provider on this channel. Since the machine itself is what's being leased out to untrusted users, we will assign this Cloud Pub/Sub topic and give it restricted permissions which only allow it to subscribe to the one topic. On the other hand, the backend is trusted so we allow it to choose its own topic. When a backend adds a machine to the Catalog, it should provide the Pub/Sub topic and project to communicate on regarding the machine, as well as the service account on the machine itself which will be used to authenticate pull requests on the subscription created by the Machine Provider for the machine.",
-          "required": true
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest": {
-      "description": "Represents a batched set of CatalogMachineAdditionRequests. dimensions.backend must be specified in each CatalogMachineAdditionRequest. dimensions.hostname must be unique per backend.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest",
-      "properties": {
-        "requests": {
-          "description": "Represents a request to add a machine to the catalog. dimensions.backend must be specified. dimensions.hostname must be unique per backend.",
-          "items": {
-            "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest"
-          },
-          "type": "array"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest": {
-      "description": "Represents a request to delete a machine in the catalog.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest",
-      "properties": {
-        "dimensions": {
-          "$ref": "ComponentsMachineProviderDimensionsDimensions",
-          "description": "Represents the dimensions of a machine.",
-          "required": true
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest": {
-      "description": "Represents a request to retrieve a machine from the catalog.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest",
-      "properties": {
-        "backend": {
-          "enum": [
-            "DUMMY",
-            "GCE",
-            "VSPHERE"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "hostname": {
-          "required": true,
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse": {
-      "description": "Represents a response to a catalog machine retrieval request.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse",
-      "properties": {
-        "dimensions": {
-          "$ref": "ComponentsMachineProviderDimensionsDimensions",
-          "description": "Represents the dimensions of a machine."
-        },
-        "lease_expiration_ts": {
-          "format": "int64",
-          "type": "string"
-        },
-        "leased_indefinitely": {
-          "type": "boolean"
-        },
-        "policies": {
-          "$ref": "ComponentsMachineProviderPoliciesPolicies",
-          "description": "Represents the policies for a machine. There are two Pub/Sub channels of communication for each machine. One is the backend-level channel which the Machine Provider will use to tell the backend that the machine has been leased, or that the machine needs to be reclaimed. The other is the channel between the Machine Provider and the machine itself. The machine should listen for instructions from the Machine Provider on this channel. Since the machine itself is what's being leased out to untrusted users, we will assign this Cloud Pub/Sub topic and give it restricted permissions which only allow it to subscribe to the one topic. On the other hand, the backend is trusted so we allow it to choose its own topic. When a backend adds a machine to the Catalog, it should provide the Pub/Sub topic and project to communicate on regarding the machine, as well as the service account on the machine itself which will be used to authenticate pull requests on the subscription created by the Machine Provider for the machine."
-        },
-        "pubsub_subscription": {
-          "type": "string"
-        },
-        "pubsub_subscription_project": {
-          "type": "string"
-        },
-        "pubsub_topic": {
-          "type": "string"
-        },
-        "pubsub_topic_project": {
-          "type": "string"
-        },
-        "state": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse": {
-      "description": "Represents a response to a catalog manipulation request.",
-      "id": "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse",
-      "properties": {
-        "error": {
-          "enum": [
-            "ENTRY_NOT_FOUND",
-            "HOSTNAME_REUSE",
-            "INVALID_PROJECT",
-            "INVALID_TOPIC",
-            "LEASED",
-            "MISMATCHED_BACKEND",
-            "UNSPECIFIED_BACKEND",
-            "UNSPECIFIED_HOSTNAME",
-            "UNSPECIFIED_TOPIC"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            "",
-            "",
-            "",
-            "",
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "machine_addition_request": {
-          "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest",
-          "description": "Represents a request to add a machine to the catalog. dimensions.backend must be specified. dimensions.hostname must be unique per backend."
-        },
-        "machine_deletion_request": {
-          "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest",
-          "description": "Represents a request to delete a machine in the catalog."
-        }
-      },
-      "type": "object"
-    }
-  },
-  "servicePath": "catalog/v1/",
-  "version": "v1"
-}
\ No newline at end of file
diff --git a/common/api/machine_provider/catalog/v1/catalog-gen.go b/common/api/machine_provider/catalog/v1/catalog-gen.go
deleted file mode 100644
index 807c787..0000000
--- a/common/api/machine_provider/catalog/v1/catalog-gen.go
+++ /dev/null
@@ -1,1097 +0,0 @@
-// Copyright 2019 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Code generated file. DO NOT EDIT.
-
-// Package catalog provides access to the .
-//
-// Creating a client
-//
-// Usage example:
-//
-//   import "go.chromium.org/luci/common/api/machine_provider/catalog/v1"
-//   ...
-//   ctx := context.Background()
-//   catalogService, err := catalog.NewService(ctx)
-//
-// In this example, Google Application Default Credentials are used for authentication.
-//
-// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
-//
-// Other authentication options
-//
-// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
-//
-//   catalogService, err := catalog.NewService(ctx, option.WithAPIKey("AIza..."))
-//
-// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
-//
-//   config := &oauth2.Config{...}
-//   // ...
-//   token, err := config.Exchange(ctx, ...)
-//   catalogService, err := catalog.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
-//
-// See https://godoc.org/google.golang.org/api/option/ for details on options.
-package catalog // import "go.chromium.org/luci/common/api/machine_provider/catalog/v1"
-
-import (
-	"bytes"
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"net/http"
-	"net/url"
-	"strconv"
-	"strings"
-
-	gensupport "google.golang.org/api/gensupport"
-	googleapi "google.golang.org/api/googleapi"
-	option "google.golang.org/api/option"
-	htransport "google.golang.org/api/transport/http"
-)
-
-// Always reference these packages, just in case the auto-generated code
-// below doesn't.
-var _ = bytes.NewBuffer
-var _ = strconv.Itoa
-var _ = fmt.Sprintf
-var _ = json.NewDecoder
-var _ = io.Copy
-var _ = url.Parse
-var _ = gensupport.MarshalJSON
-var _ = googleapi.Version
-var _ = errors.New
-var _ = strings.Replace
-var _ = context.Canceled
-
-const apiId = "catalog:v1"
-const apiName = "catalog"
-const apiVersion = "v1"
-const basePath = "http://localhost:8080/_ah/api/catalog/v1"
-
-// OAuth2 scopes used by this API.
-const (
-	// https://www.googleapis.com/auth/userinfo.email
-	UserinfoEmailScope = "https://www.googleapis.com/auth/userinfo.email"
-)
-
-// NewService creates a new Service.
-func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
-	scopesOption := option.WithScopes(
-		"https://www.googleapis.com/auth/userinfo.email",
-	)
-	// NOTE: prepend, so we don't override user-specified scopes.
-	opts = append([]option.ClientOption{scopesOption}, opts...)
-	client, endpoint, err := htransport.NewClient(ctx, opts...)
-	if err != nil {
-		return nil, err
-	}
-	s, err := New(client)
-	if err != nil {
-		return nil, err
-	}
-	if endpoint != "" {
-		s.BasePath = endpoint
-	}
-	return s, nil
-}
-
-// New creates a new Service. It uses the provided http.Client for requests.
-//
-// Deprecated: please use NewService instead.
-// To provide a custom HTTP client, use option.WithHTTPClient.
-// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
-func New(client *http.Client) (*Service, error) {
-	if client == nil {
-		return nil, errors.New("client is nil")
-	}
-	s := &Service{client: client, BasePath: basePath}
-	return s, nil
-}
-
-type Service struct {
-	client    *http.Client
-	BasePath  string // API endpoint base URL
-	UserAgent string // optional additional User-Agent fragment
-}
-
-func (s *Service) userAgent() string {
-	if s.UserAgent == "" {
-		return googleapi.UserAgent
-	}
-	return googleapi.UserAgent + " " + s.UserAgent
-}
-
-// ComponentsMachineProviderDimensionsDimensions: Represents the
-// dimensions of a machine.
-type ComponentsMachineProviderDimensionsDimensions struct {
-	// Possible values:
-	//   "DUMMY"
-	//   "GCE"
-	//   "VSPHERE"
-	Backend string `json:"backend,omitempty"`
-
-	DiskGb int64 `json:"disk_gb,omitempty,string"`
-
-	// Possible values:
-	//   "HDD"
-	//   "SSD"
-	DiskType string `json:"disk_type,omitempty"`
-
-	Hostname string `json:"hostname,omitempty"`
-
-	// Possible values:
-	//   "DEBIAN"
-	//   "UBUNTU"
-	LinuxFlavor string `json:"linux_flavor,omitempty"`
-
-	MemoryGb float64 `json:"memory_gb,omitempty"`
-
-	NumCpus int64 `json:"num_cpus,omitempty,string"`
-
-	// Possible values:
-	//   "LINUX"
-	//   "OSX"
-	//   "WINDOWS"
-	OsFamily string `json:"os_family,omitempty"`
-
-	OsVersion string `json:"os_version,omitempty"`
-
-	Project string `json:"project,omitempty"`
-
-	Snapshot string `json:"snapshot,omitempty"`
-
-	SnapshotLabels []string `json:"snapshot_labels,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Backend") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Backend") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderDimensionsDimensions) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderDimensionsDimensions
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-func (s *ComponentsMachineProviderDimensionsDimensions) UnmarshalJSON(data []byte) error {
-	type NoMethod ComponentsMachineProviderDimensionsDimensions
-	var s1 struct {
-		MemoryGb gensupport.JSONFloat64 `json:"memory_gb"`
-		*NoMethod
-	}
-	s1.NoMethod = (*NoMethod)(s)
-	if err := json.Unmarshal(data, &s1); err != nil {
-		return err
-	}
-	s.MemoryGb = float64(s1.MemoryGb)
-	return nil
-}
-
-// ComponentsMachineProviderPoliciesKeyValuePair: Represents a key-value
-// pair.
-type ComponentsMachineProviderPoliciesKeyValuePair struct {
-	Key string `json:"key,omitempty"`
-
-	Value string `json:"value,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Key") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Key") to include in API
-	// requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderPoliciesKeyValuePair) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderPoliciesKeyValuePair
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderPoliciesPolicies: Represents the policies
-// for a machine. There are two Pub/Sub channels of communication for
-// each machine. One is the backend-level channel which the Machine
-// Provider will use to tell the backend that the machine has been
-// leased, or that the machine needs to be reclaimed. The other is the
-// channel between the Machine Provider and the machine itself. The
-// machine should listen for instructions from the Machine Provider on
-// this channel. Since the machine itself is what's being leased out to
-// untrusted users, we will assign this Cloud Pub/Sub topic and give it
-// restricted permissions which only allow it to subscribe to the one
-// topic. On the other hand, the backend is trusted so we allow it to
-// choose its own topic. When a backend adds a machine to the Catalog,
-// it should provide the Pub/Sub topic and project to communicate on
-// regarding the machine, as well as the service account on the machine
-// itself which will be used to authenticate pull requests on the
-// subscription created by the Machine Provider for the machine.
-type ComponentsMachineProviderPoliciesPolicies struct {
-	// BackendAttributes: Represents a key-value pair.
-	BackendAttributes []*ComponentsMachineProviderPoliciesKeyValuePair `json:"backend_attributes,omitempty"`
-
-	BackendProject string `json:"backend_project,omitempty"`
-
-	BackendTopic string `json:"backend_topic,omitempty"`
-
-	MachineServiceAccount string `json:"machine_service_account,omitempty"`
-
-	// Possible values:
-	//   "DELETE"
-	//   "MAKE_AVAILABLE" (default)
-	//   "RECLAIM"
-	OnReclamation string `json:"on_reclamation,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "BackendAttributes")
-	// to unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "BackendAttributes") to
-	// include in API requests with the JSON null value. By default, fields
-	// with empty values are omitted from API requests. However, any field
-	// with an empty value appearing in NullFields will be sent to the
-	// server as null. It is an error if a field in this list has a
-	// non-empty value. This may be used to include null fields in Patch
-	// requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderPoliciesPolicies) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderPoliciesPolicies
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse:
-// Represents a response to a batched catalog manipulation request.
-type ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse struct {
-	// Responses: Represents a response to a catalog manipulation request.
-	Responses []*ComponentsMachineProviderRpcMessagesCatalogManipulationResponse `json:"responses,omitempty"`
-
-	// ServerResponse contains the HTTP response code and headers from the
-	// server.
-	googleapi.ServerResponse `json:"-"`
-
-	// ForceSendFields is a list of field names (e.g. "Responses") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Responses") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest:
-// Represents a request to add a machine to the catalog.
-// dimensions.backend must be specified. dimensions.hostname must be
-// unique per backend.
-type ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest struct {
-	// Dimensions: Represents the dimensions of a machine.
-	Dimensions *ComponentsMachineProviderDimensionsDimensions `json:"dimensions,omitempty"`
-
-	// Policies: Represents the policies for a machine. There are two
-	// Pub/Sub channels of communication for each machine. One is the
-	// backend-level channel which the Machine Provider will use to tell the
-	// backend that the machine has been leased, or that the machine needs
-	// to be reclaimed. The other is the channel between the Machine
-	// Provider and the machine itself. The machine should listen for
-	// instructions from the Machine Provider on this channel. Since the
-	// machine itself is what's being leased out to untrusted users, we will
-	// assign this Cloud Pub/Sub topic and give it restricted permissions
-	// which only allow it to subscribe to the one topic. On the other hand,
-	// the backend is trusted so we allow it to choose its own topic. When a
-	// backend adds a machine to the Catalog, it should provide the Pub/Sub
-	// topic and project to communicate on regarding the machine, as well as
-	// the service account on the machine itself which will be used to
-	// authenticate pull requests on the subscription created by the Machine
-	// Provider for the machine.
-	Policies *ComponentsMachineProviderPoliciesPolicies `json:"policies,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Dimensions") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Dimensions") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest
-// : Represents a batched set of CatalogMachineAdditionRequests.
-// dimensions.backend must be specified in each
-// CatalogMachineAdditionRequest. dimensions.hostname must be unique per
-// backend.
-type ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest struct {
-	// Requests: Represents a request to add a machine to the catalog.
-	// dimensions.backend must be specified. dimensions.hostname must be
-	// unique per backend.
-	Requests []*ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest `json:"requests,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Requests") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Requests") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest:
-// Represents a request to delete a machine in the catalog.
-type ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest struct {
-	// Dimensions: Represents the dimensions of a machine.
-	Dimensions *ComponentsMachineProviderDimensionsDimensions `json:"dimensions,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Dimensions") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Dimensions") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest:
-// Represents a request to retrieve a machine from the catalog.
-type ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest struct {
-	// Possible values:
-	//   "DUMMY"
-	//   "GCE"
-	//   "VSPHERE"
-	Backend string `json:"backend,omitempty"`
-
-	Hostname string `json:"hostname,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Backend") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Backend") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse:
-// Represents a response to a catalog machine retrieval request.
-type ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse struct {
-	// Dimensions: Represents the dimensions of a machine.
-	Dimensions *ComponentsMachineProviderDimensionsDimensions `json:"dimensions,omitempty"`
-
-	LeaseExpirationTs int64 `json:"lease_expiration_ts,omitempty,string"`
-
-	LeasedIndefinitely bool `json:"leased_indefinitely,omitempty"`
-
-	// Policies: Represents the policies for a machine. There are two
-	// Pub/Sub channels of communication for each machine. One is the
-	// backend-level channel which the Machine Provider will use to tell the
-	// backend that the machine has been leased, or that the machine needs
-	// to be reclaimed. The other is the channel between the Machine
-	// Provider and the machine itself. The machine should listen for
-	// instructions from the Machine Provider on this channel. Since the
-	// machine itself is what's being leased out to untrusted users, we will
-	// assign this Cloud Pub/Sub topic and give it restricted permissions
-	// which only allow it to subscribe to the one topic. On the other hand,
-	// the backend is trusted so we allow it to choose its own topic. When a
-	// backend adds a machine to the Catalog, it should provide the Pub/Sub
-	// topic and project to communicate on regarding the machine, as well as
-	// the service account on the machine itself which will be used to
-	// authenticate pull requests on the subscription created by the Machine
-	// Provider for the machine.
-	Policies *ComponentsMachineProviderPoliciesPolicies `json:"policies,omitempty"`
-
-	PubsubSubscription string `json:"pubsub_subscription,omitempty"`
-
-	PubsubSubscriptionProject string `json:"pubsub_subscription_project,omitempty"`
-
-	PubsubTopic string `json:"pubsub_topic,omitempty"`
-
-	PubsubTopicProject string `json:"pubsub_topic_project,omitempty"`
-
-	State string `json:"state,omitempty"`
-
-	// ServerResponse contains the HTTP response code and headers from the
-	// server.
-	googleapi.ServerResponse `json:"-"`
-
-	// ForceSendFields is a list of field names (e.g. "Dimensions") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Dimensions") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesCatalogManipulationResponse:
-// Represents a response to a catalog manipulation request.
-type ComponentsMachineProviderRpcMessagesCatalogManipulationResponse struct {
-	// Possible values:
-	//   "ENTRY_NOT_FOUND"
-	//   "HOSTNAME_REUSE"
-	//   "INVALID_PROJECT"
-	//   "INVALID_TOPIC"
-	//   "LEASED"
-	//   "MISMATCHED_BACKEND"
-	//   "UNSPECIFIED_BACKEND"
-	//   "UNSPECIFIED_HOSTNAME"
-	//   "UNSPECIFIED_TOPIC"
-	Error string `json:"error,omitempty"`
-
-	// MachineAdditionRequest: Represents a request to add a machine to the
-	// catalog. dimensions.backend must be specified. dimensions.hostname
-	// must be unique per backend.
-	MachineAdditionRequest *ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest `json:"machine_addition_request,omitempty"`
-
-	// MachineDeletionRequest: Represents a request to delete a machine in
-	// the catalog.
-	MachineDeletionRequest *ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest `json:"machine_deletion_request,omitempty"`
-
-	// ServerResponse contains the HTTP response code and headers from the
-	// server.
-	googleapi.ServerResponse `json:"-"`
-
-	// ForceSendFields is a list of field names (e.g. "Error") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Error") to include in API
-	// requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesCatalogManipulationResponse) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesCatalogManipulationResponse
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// method id "catalog.add_machine":
-
-type AddMachineCall struct {
-	s                                                                 *Service
-	componentsmachineproviderrpcmessagescatalogmachineadditionrequest *ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest
-	urlParams_                                                        gensupport.URLParams
-	ctx_                                                              context.Context
-	header_                                                           http.Header
-}
-
-// AddMachine: Handles an incoming CatalogMachineAdditionRequest.
-func (s *Service) AddMachine(componentsmachineproviderrpcmessagescatalogmachineadditionrequest *ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest) *AddMachineCall {
-	c := &AddMachineCall{s: s, urlParams_: make(gensupport.URLParams)}
-	c.componentsmachineproviderrpcmessagescatalogmachineadditionrequest = componentsmachineproviderrpcmessagescatalogmachineadditionrequest
-	return c
-}
-
-// Fields allows partial responses to be retrieved. See
-// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
-// for more information.
-func (c *AddMachineCall) Fields(s ...googleapi.Field) *AddMachineCall {
-	c.urlParams_.Set("fields", googleapi.CombineFields(s))
-	return c
-}
-
-// Context sets the context to be used in this call's Do method. Any
-// pending HTTP request will be aborted if the provided context is
-// canceled.
-func (c *AddMachineCall) Context(ctx context.Context) *AddMachineCall {
-	c.ctx_ = ctx
-	return c
-}
-
-// Header returns an http.Header that can be modified by the caller to
-// add HTTP headers to the request.
-func (c *AddMachineCall) Header() http.Header {
-	if c.header_ == nil {
-		c.header_ = make(http.Header)
-	}
-	return c.header_
-}
-
-func (c *AddMachineCall) doRequest(alt string) (*http.Response, error) {
-	reqHeaders := make(http.Header)
-	for k, v := range c.header_ {
-		reqHeaders[k] = v
-	}
-	reqHeaders.Set("User-Agent", c.s.userAgent())
-	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.componentsmachineproviderrpcmessagescatalogmachineadditionrequest)
-	if err != nil {
-		return nil, err
-	}
-	reqHeaders.Set("Content-Type", "application/json")
-	c.urlParams_.Set("alt", alt)
-	c.urlParams_.Set("prettyPrint", "false")
-	urls := googleapi.ResolveRelative(c.s.BasePath, "add_machine")
-	urls += "?" + c.urlParams_.Encode()
-	req, err := http.NewRequest("POST", urls, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header = reqHeaders
-	return gensupport.SendRequest(c.ctx_, c.s.client, req)
-}
-
-// Do executes the "catalog.add_machine" call.
-// Exactly one of
-// *ComponentsMachineProviderRpcMessagesCatalogManipulationResponse or
-// error will be non-nil. Any non-2xx status code is an error. Response
-// headers are in either
-// *ComponentsMachineProviderRpcMessagesCatalogManipulationResponse.Serve
-// rResponse.Header or (if a response was returned at all) in
-// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
-// whether the returned error was because http.StatusNotModified was
-// returned.
-func (c *AddMachineCall) Do(opts ...googleapi.CallOption) (*ComponentsMachineProviderRpcMessagesCatalogManipulationResponse, error) {
-	gensupport.SetOptions(c.urlParams_, opts...)
-	res, err := c.doRequest("json")
-	if res != nil && res.StatusCode == http.StatusNotModified {
-		if res.Body != nil {
-			res.Body.Close()
-		}
-		return nil, &googleapi.Error{
-			Code:   res.StatusCode,
-			Header: res.Header,
-		}
-	}
-	if err != nil {
-		return nil, err
-	}
-	defer googleapi.CloseBody(res)
-	if err := googleapi.CheckResponse(res); err != nil {
-		return nil, err
-	}
-	ret := &ComponentsMachineProviderRpcMessagesCatalogManipulationResponse{
-		ServerResponse: googleapi.ServerResponse{
-			Header:         res.Header,
-			HTTPStatusCode: res.StatusCode,
-		},
-	}
-	target := &ret
-	if err := gensupport.DecodeResponse(target, res); err != nil {
-		return nil, err
-	}
-	return ret, nil
-	// {
-	//   "description": "Handles an incoming CatalogMachineAdditionRequest.",
-	//   "httpMethod": "POST",
-	//   "id": "catalog.add_machine",
-	//   "path": "add_machine",
-	//   "request": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineAdditionRequest",
-	//     "parameterName": "resource"
-	//   },
-	//   "response": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse"
-	//   },
-	//   "scopes": [
-	//     "https://www.googleapis.com/auth/userinfo.email"
-	//   ]
-	// }
-
-}
-
-// method id "catalog.add_machines":
-
-type AddMachinesCall struct {
-	s                                                                      *Service
-	componentsmachineproviderrpcmessagescatalogmachinebatchadditionrequest *ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest
-	urlParams_                                                             gensupport.URLParams
-	ctx_                                                                   context.Context
-	header_                                                                http.Header
-}
-
-// AddMachines: Handles an incoming CatalogMachineBatchAdditionRequest.
-// Batches are intended to save on RPCs only. The batched requests will
-// not execute transactionally.
-func (s *Service) AddMachines(componentsmachineproviderrpcmessagescatalogmachinebatchadditionrequest *ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest) *AddMachinesCall {
-	c := &AddMachinesCall{s: s, urlParams_: make(gensupport.URLParams)}
-	c.componentsmachineproviderrpcmessagescatalogmachinebatchadditionrequest = componentsmachineproviderrpcmessagescatalogmachinebatchadditionrequest
-	return c
-}
-
-// Fields allows partial responses to be retrieved. See
-// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
-// for more information.
-func (c *AddMachinesCall) Fields(s ...googleapi.Field) *AddMachinesCall {
-	c.urlParams_.Set("fields", googleapi.CombineFields(s))
-	return c
-}
-
-// Context sets the context to be used in this call's Do method. Any
-// pending HTTP request will be aborted if the provided context is
-// canceled.
-func (c *AddMachinesCall) Context(ctx context.Context) *AddMachinesCall {
-	c.ctx_ = ctx
-	return c
-}
-
-// Header returns an http.Header that can be modified by the caller to
-// add HTTP headers to the request.
-func (c *AddMachinesCall) Header() http.Header {
-	if c.header_ == nil {
-		c.header_ = make(http.Header)
-	}
-	return c.header_
-}
-
-func (c *AddMachinesCall) doRequest(alt string) (*http.Response, error) {
-	reqHeaders := make(http.Header)
-	for k, v := range c.header_ {
-		reqHeaders[k] = v
-	}
-	reqHeaders.Set("User-Agent", c.s.userAgent())
-	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.componentsmachineproviderrpcmessagescatalogmachinebatchadditionrequest)
-	if err != nil {
-		return nil, err
-	}
-	reqHeaders.Set("Content-Type", "application/json")
-	c.urlParams_.Set("alt", alt)
-	c.urlParams_.Set("prettyPrint", "false")
-	urls := googleapi.ResolveRelative(c.s.BasePath, "add_machines")
-	urls += "?" + c.urlParams_.Encode()
-	req, err := http.NewRequest("POST", urls, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header = reqHeaders
-	return gensupport.SendRequest(c.ctx_, c.s.client, req)
-}
-
-// Do executes the "catalog.add_machines" call.
-// Exactly one of
-// *ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse
-// or error will be non-nil. Any non-2xx status code is an error.
-// Response headers are in either
-// *ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse.
-// ServerResponse.Header or (if a response was returned at all) in
-// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
-// whether the returned error was because http.StatusNotModified was
-// returned.
-func (c *AddMachinesCall) Do(opts ...googleapi.CallOption) (*ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse, error) {
-	gensupport.SetOptions(c.urlParams_, opts...)
-	res, err := c.doRequest("json")
-	if res != nil && res.StatusCode == http.StatusNotModified {
-		if res.Body != nil {
-			res.Body.Close()
-		}
-		return nil, &googleapi.Error{
-			Code:   res.StatusCode,
-			Header: res.Header,
-		}
-	}
-	if err != nil {
-		return nil, err
-	}
-	defer googleapi.CloseBody(res)
-	if err := googleapi.CheckResponse(res); err != nil {
-		return nil, err
-	}
-	ret := &ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse{
-		ServerResponse: googleapi.ServerResponse{
-			Header:         res.Header,
-			HTTPStatusCode: res.StatusCode,
-		},
-	}
-	target := &ret
-	if err := gensupport.DecodeResponse(target, res); err != nil {
-		return nil, err
-	}
-	return ret, nil
-	// {
-	//   "description": "Handles an incoming CatalogMachineBatchAdditionRequest. Batches are intended to save on RPCs only. The batched requests will not execute transactionally.",
-	//   "httpMethod": "POST",
-	//   "id": "catalog.add_machines",
-	//   "path": "add_machines",
-	//   "request": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineBatchAdditionRequest",
-	//     "parameterName": "resource"
-	//   },
-	//   "response": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogBatchManipulationResponse"
-	//   },
-	//   "scopes": [
-	//     "https://www.googleapis.com/auth/userinfo.email"
-	//   ]
-	// }
-
-}
-
-// method id "catalog.delete_machine":
-
-type DeleteMachineCall struct {
-	s                                                                 *Service
-	componentsmachineproviderrpcmessagescatalogmachinedeletionrequest *ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest
-	urlParams_                                                        gensupport.URLParams
-	ctx_                                                              context.Context
-	header_                                                           http.Header
-}
-
-// DeleteMachine: Handles an incoming CatalogMachineDeletionRequest.
-func (s *Service) DeleteMachine(componentsmachineproviderrpcmessagescatalogmachinedeletionrequest *ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest) *DeleteMachineCall {
-	c := &DeleteMachineCall{s: s, urlParams_: make(gensupport.URLParams)}
-	c.componentsmachineproviderrpcmessagescatalogmachinedeletionrequest = componentsmachineproviderrpcmessagescatalogmachinedeletionrequest
-	return c
-}
-
-// Fields allows partial responses to be retrieved. See
-// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
-// for more information.
-func (c *DeleteMachineCall) Fields(s ...googleapi.Field) *DeleteMachineCall {
-	c.urlParams_.Set("fields", googleapi.CombineFields(s))
-	return c
-}
-
-// Context sets the context to be used in this call's Do method. Any
-// pending HTTP request will be aborted if the provided context is
-// canceled.
-func (c *DeleteMachineCall) Context(ctx context.Context) *DeleteMachineCall {
-	c.ctx_ = ctx
-	return c
-}
-
-// Header returns an http.Header that can be modified by the caller to
-// add HTTP headers to the request.
-func (c *DeleteMachineCall) Header() http.Header {
-	if c.header_ == nil {
-		c.header_ = make(http.Header)
-	}
-	return c.header_
-}
-
-func (c *DeleteMachineCall) doRequest(alt string) (*http.Response, error) {
-	reqHeaders := make(http.Header)
-	for k, v := range c.header_ {
-		reqHeaders[k] = v
-	}
-	reqHeaders.Set("User-Agent", c.s.userAgent())
-	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.componentsmachineproviderrpcmessagescatalogmachinedeletionrequest)
-	if err != nil {
-		return nil, err
-	}
-	reqHeaders.Set("Content-Type", "application/json")
-	c.urlParams_.Set("alt", alt)
-	c.urlParams_.Set("prettyPrint", "false")
-	urls := googleapi.ResolveRelative(c.s.BasePath, "delete_machine")
-	urls += "?" + c.urlParams_.Encode()
-	req, err := http.NewRequest("POST", urls, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header = reqHeaders
-	return gensupport.SendRequest(c.ctx_, c.s.client, req)
-}
-
-// Do executes the "catalog.delete_machine" call.
-// Exactly one of
-// *ComponentsMachineProviderRpcMessagesCatalogManipulationResponse or
-// error will be non-nil. Any non-2xx status code is an error. Response
-// headers are in either
-// *ComponentsMachineProviderRpcMessagesCatalogManipulationResponse.Serve
-// rResponse.Header or (if a response was returned at all) in
-// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
-// whether the returned error was because http.StatusNotModified was
-// returned.
-func (c *DeleteMachineCall) Do(opts ...googleapi.CallOption) (*ComponentsMachineProviderRpcMessagesCatalogManipulationResponse, error) {
-	gensupport.SetOptions(c.urlParams_, opts...)
-	res, err := c.doRequest("json")
-	if res != nil && res.StatusCode == http.StatusNotModified {
-		if res.Body != nil {
-			res.Body.Close()
-		}
-		return nil, &googleapi.Error{
-			Code:   res.StatusCode,
-			Header: res.Header,
-		}
-	}
-	if err != nil {
-		return nil, err
-	}
-	defer googleapi.CloseBody(res)
-	if err := googleapi.CheckResponse(res); err != nil {
-		return nil, err
-	}
-	ret := &ComponentsMachineProviderRpcMessagesCatalogManipulationResponse{
-		ServerResponse: googleapi.ServerResponse{
-			Header:         res.Header,
-			HTTPStatusCode: res.StatusCode,
-		},
-	}
-	target := &ret
-	if err := gensupport.DecodeResponse(target, res); err != nil {
-		return nil, err
-	}
-	return ret, nil
-	// {
-	//   "description": "Handles an incoming CatalogMachineDeletionRequest.",
-	//   "httpMethod": "POST",
-	//   "id": "catalog.delete_machine",
-	//   "path": "delete_machine",
-	//   "request": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineDeletionRequest",
-	//     "parameterName": "resource"
-	//   },
-	//   "response": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogManipulationResponse"
-	//   },
-	//   "scopes": [
-	//     "https://www.googleapis.com/auth/userinfo.email"
-	//   ]
-	// }
-
-}
-
-// method id "catalog.get":
-
-type GetCall struct {
-	s                                                                  *Service
-	componentsmachineproviderrpcmessagescatalogmachineretrievalrequest *ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest
-	urlParams_                                                         gensupport.URLParams
-	ctx_                                                               context.Context
-	header_                                                            http.Header
-}
-
-// Get: Handles an incoming CatalogMachineRetrievalRequest.
-func (s *Service) Get(componentsmachineproviderrpcmessagescatalogmachineretrievalrequest *ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest) *GetCall {
-	c := &GetCall{s: s, urlParams_: make(gensupport.URLParams)}
-	c.componentsmachineproviderrpcmessagescatalogmachineretrievalrequest = componentsmachineproviderrpcmessagescatalogmachineretrievalrequest
-	return c
-}
-
-// Fields allows partial responses to be retrieved. See
-// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
-// for more information.
-func (c *GetCall) Fields(s ...googleapi.Field) *GetCall {
-	c.urlParams_.Set("fields", googleapi.CombineFields(s))
-	return c
-}
-
-// Context sets the context to be used in this call's Do method. Any
-// pending HTTP request will be aborted if the provided context is
-// canceled.
-func (c *GetCall) Context(ctx context.Context) *GetCall {
-	c.ctx_ = ctx
-	return c
-}
-
-// Header returns an http.Header that can be modified by the caller to
-// add HTTP headers to the request.
-func (c *GetCall) Header() http.Header {
-	if c.header_ == nil {
-		c.header_ = make(http.Header)
-	}
-	return c.header_
-}
-
-func (c *GetCall) doRequest(alt string) (*http.Response, error) {
-	reqHeaders := make(http.Header)
-	for k, v := range c.header_ {
-		reqHeaders[k] = v
-	}
-	reqHeaders.Set("User-Agent", c.s.userAgent())
-	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.componentsmachineproviderrpcmessagescatalogmachineretrievalrequest)
-	if err != nil {
-		return nil, err
-	}
-	reqHeaders.Set("Content-Type", "application/json")
-	c.urlParams_.Set("alt", alt)
-	c.urlParams_.Set("prettyPrint", "false")
-	urls := googleapi.ResolveRelative(c.s.BasePath, "get")
-	urls += "?" + c.urlParams_.Encode()
-	req, err := http.NewRequest("POST", urls, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header = reqHeaders
-	return gensupport.SendRequest(c.ctx_, c.s.client, req)
-}
-
-// Do executes the "catalog.get" call.
-// Exactly one of
-// *ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse
-// or error will be non-nil. Any non-2xx status code is an error.
-// Response headers are in either
-// *ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse.S
-// erverResponse.Header or (if a response was returned at all) in
-// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
-// whether the returned error was because http.StatusNotModified was
-// returned.
-func (c *GetCall) Do(opts ...googleapi.CallOption) (*ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse, error) {
-	gensupport.SetOptions(c.urlParams_, opts...)
-	res, err := c.doRequest("json")
-	if res != nil && res.StatusCode == http.StatusNotModified {
-		if res.Body != nil {
-			res.Body.Close()
-		}
-		return nil, &googleapi.Error{
-			Code:   res.StatusCode,
-			Header: res.Header,
-		}
-	}
-	if err != nil {
-		return nil, err
-	}
-	defer googleapi.CloseBody(res)
-	if err := googleapi.CheckResponse(res); err != nil {
-		return nil, err
-	}
-	ret := &ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse{
-		ServerResponse: googleapi.ServerResponse{
-			Header:         res.Header,
-			HTTPStatusCode: res.StatusCode,
-		},
-	}
-	target := &ret
-	if err := gensupport.DecodeResponse(target, res); err != nil {
-		return nil, err
-	}
-	return ret, nil
-	// {
-	//   "description": "Handles an incoming CatalogMachineRetrievalRequest.",
-	//   "httpMethod": "POST",
-	//   "id": "catalog.get",
-	//   "path": "get",
-	//   "request": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalRequest",
-	//     "parameterName": "resource"
-	//   },
-	//   "response": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesCatalogMachineRetrievalResponse"
-	//   },
-	//   "scopes": [
-	//     "https://www.googleapis.com/auth/userinfo.email"
-	//   ]
-	// }
-
-}
diff --git a/common/api/machine_provider/machine/v1/machine-api.json b/common/api/machine_provider/machine/v1/machine-api.json
deleted file mode 100644
index 23d4b35..0000000
--- a/common/api/machine_provider/machine/v1/machine-api.json
+++ /dev/null
@@ -1,177 +0,0 @@
-{
-  "auth": {
-    "oauth2": {
-      "scopes": {
-        "https://www.googleapis.com/auth/userinfo.email": {
-          "description": "https://www.googleapis.com/auth/userinfo.email"
-        }
-      }
-    }
-  },
-  "basePath": "/_ah/api/machine/v1",
-  "baseUrl": "https://machine-provider.appspot.com/_ah/api/machine/v1",
-  "batchPath": "batch",
-  "description": "Implements cloud endpoints for Machine Provider's machines.",
-  "discoveryVersion": "v1",
-  "icons": {
-    "x16": "https://www.google.com/images/icons/product/search-16.gif",
-    "x32": "https://www.google.com/images/icons/product/search-32.gif"
-  },
-  "id": "machine:v1",
-  "kind": "discovery#restDescription",
-  "methods": {
-    "ack": {
-      "description": "Handles an incoming AckRequest.",
-      "httpMethod": "POST",
-      "id": "machine.ack",
-      "path": "ack",
-      "request": {
-        "$ref": "ComponentsMachineProviderRpcMessagesAckRequest",
-        "parameterName": "resource"
-      },
-      "scopes": [
-        "https://www.googleapis.com/auth/userinfo.email"
-      ]
-    },
-    "poll": {
-      "description": "Handles an incoming PollRequest.",
-      "httpMethod": "POST",
-      "id": "machine.poll",
-      "path": "poll",
-      "request": {
-        "$ref": "ComponentsMachineProviderRpcMessagesPollRequest",
-        "parameterName": "resource"
-      },
-      "response": {
-        "$ref": "ComponentsMachineProviderRpcMessagesPollResponse"
-      },
-      "scopes": [
-        "https://www.googleapis.com/auth/userinfo.email"
-      ]
-    }
-  },
-  "name": "machine",
-  "parameters": {
-    "alt": {
-      "default": "json",
-      "description": "Data format for the response.",
-      "enum": [
-        "json"
-      ],
-      "enumDescriptions": [
-        "Responses with Content-Type of application/json"
-      ],
-      "location": "query",
-      "type": "string"
-    },
-    "fields": {
-      "description": "Selector specifying which fields to include in a partial response.",
-      "location": "query",
-      "type": "string"
-    },
-    "key": {
-      "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",
-      "type": "string"
-    },
-    "oauth_token": {
-      "description": "OAuth 2.0 token for the current user.",
-      "location": "query",
-      "type": "string"
-    },
-    "prettyPrint": {
-      "default": "true",
-      "description": "Returns response with indentations and line breaks.",
-      "location": "query",
-      "type": "boolean"
-    },
-    "quotaUser": {
-      "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",
-      "type": "string"
-    },
-    "userIp": {
-      "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
-      "location": "query",
-      "type": "string"
-    }
-  },
-  "protocol": "rest",
-  "rootUrl": "https://machine-provider.appspot.com/_ah/api/",
-  "schemas": {
-    "ComponentsMachineProviderInstructionsInstruction": {
-      "description": "Represents instructions for a machine.",
-      "id": "ComponentsMachineProviderInstructionsInstruction",
-      "properties": {
-        "swarming_server": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesAckRequest": {
-      "description": "Represents a request to ack an instruction received by a machine.",
-      "id": "ComponentsMachineProviderRpcMessagesAckRequest",
-      "properties": {
-        "backend": {
-          "enum": [
-            "DUMMY",
-            "GCE",
-            "VSPHERE"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "hostname": {
-          "required": true,
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesPollRequest": {
-      "description": "Represents a request to poll for instructions given to a machine.",
-      "id": "ComponentsMachineProviderRpcMessagesPollRequest",
-      "properties": {
-        "backend": {
-          "enum": [
-            "DUMMY",
-            "GCE",
-            "VSPHERE"
-          ],
-          "enumDescriptions": [
-            "",
-            "",
-            ""
-          ],
-          "type": "string"
-        },
-        "hostname": {
-          "required": true,
-          "type": "string"
-        }
-      },
-      "type": "object"
-    },
-    "ComponentsMachineProviderRpcMessagesPollResponse": {
-      "description": "Represents a response to a request for instructions given to a machine.",
-      "id": "ComponentsMachineProviderRpcMessagesPollResponse",
-      "properties": {
-        "instruction": {
-          "$ref": "ComponentsMachineProviderInstructionsInstruction",
-          "description": "Represents instructions for a machine."
-        },
-        "state": {
-          "type": "string"
-        }
-      },
-      "type": "object"
-    }
-  },
-  "servicePath": "machine/v1/",
-  "version": "v1"
-}
\ No newline at end of file
diff --git a/common/api/machine_provider/machine/v1/machine-gen.go b/common/api/machine_provider/machine/v1/machine-gen.go
deleted file mode 100644
index e5030c6..0000000
--- a/common/api/machine_provider/machine/v1/machine-gen.go
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright 2019 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Code generated file. DO NOT EDIT.
-
-// Package machine provides access to the .
-//
-// Creating a client
-//
-// Usage example:
-//
-//   import "go.chromium.org/luci/common/api/machine_provider/machine/v1"
-//   ...
-//   ctx := context.Background()
-//   machineService, err := machine.NewService(ctx)
-//
-// In this example, Google Application Default Credentials are used for authentication.
-//
-// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
-//
-// Other authentication options
-//
-// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
-//
-//   machineService, err := machine.NewService(ctx, option.WithAPIKey("AIza..."))
-//
-// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
-//
-//   config := &oauth2.Config{...}
-//   // ...
-//   token, err := config.Exchange(ctx, ...)
-//   machineService, err := machine.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
-//
-// See https://godoc.org/google.golang.org/api/option/ for details on options.
-package machine // import "go.chromium.org/luci/common/api/machine_provider/machine/v1"
-
-import (
-	"bytes"
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"net/http"
-	"net/url"
-	"strconv"
-	"strings"
-
-	gensupport "google.golang.org/api/gensupport"
-	googleapi "google.golang.org/api/googleapi"
-	option "google.golang.org/api/option"
-	htransport "google.golang.org/api/transport/http"
-)
-
-// Always reference these packages, just in case the auto-generated code
-// below doesn't.
-var _ = bytes.NewBuffer
-var _ = strconv.Itoa
-var _ = fmt.Sprintf
-var _ = json.NewDecoder
-var _ = io.Copy
-var _ = url.Parse
-var _ = gensupport.MarshalJSON
-var _ = googleapi.Version
-var _ = errors.New
-var _ = strings.Replace
-var _ = context.Canceled
-
-const apiId = "machine:v1"
-const apiName = "machine"
-const apiVersion = "v1"
-const basePath = "http://localhost:8080/_ah/api/machine/v1"
-
-// OAuth2 scopes used by this API.
-const (
-	// https://www.googleapis.com/auth/userinfo.email
-	UserinfoEmailScope = "https://www.googleapis.com/auth/userinfo.email"
-)
-
-// NewService creates a new Service.
-func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
-	scopesOption := option.WithScopes(
-		"https://www.googleapis.com/auth/userinfo.email",
-	)
-	// NOTE: prepend, so we don't override user-specified scopes.
-	opts = append([]option.ClientOption{scopesOption}, opts...)
-	client, endpoint, err := htransport.NewClient(ctx, opts...)
-	if err != nil {
-		return nil, err
-	}
-	s, err := New(client)
-	if err != nil {
-		return nil, err
-	}
-	if endpoint != "" {
-		s.BasePath = endpoint
-	}
-	return s, nil
-}
-
-// New creates a new Service. It uses the provided http.Client for requests.
-//
-// Deprecated: please use NewService instead.
-// To provide a custom HTTP client, use option.WithHTTPClient.
-// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
-func New(client *http.Client) (*Service, error) {
-	if client == nil {
-		return nil, errors.New("client is nil")
-	}
-	s := &Service{client: client, BasePath: basePath}
-	return s, nil
-}
-
-type Service struct {
-	client    *http.Client
-	BasePath  string // API endpoint base URL
-	UserAgent string // optional additional User-Agent fragment
-}
-
-func (s *Service) userAgent() string {
-	if s.UserAgent == "" {
-		return googleapi.UserAgent
-	}
-	return googleapi.UserAgent + " " + s.UserAgent
-}
-
-// ComponentsMachineProviderInstructionsInstruction: Represents
-// instructions for a machine.
-type ComponentsMachineProviderInstructionsInstruction struct {
-	SwarmingServer string `json:"swarming_server,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "SwarmingServer") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "SwarmingServer") to
-	// include in API requests with the JSON null value. By default, fields
-	// with empty values are omitted from API requests. However, any field
-	// with an empty value appearing in NullFields will be sent to the
-	// server as null. It is an error if a field in this list has a
-	// non-empty value. This may be used to include null fields in Patch
-	// requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderInstructionsInstruction) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderInstructionsInstruction
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesAckRequest: Represents a request
-// to ack an instruction received by a machine.
-type ComponentsMachineProviderRpcMessagesAckRequest struct {
-	// Possible values:
-	//   "DUMMY"
-	//   "GCE"
-	//   "VSPHERE"
-	Backend string `json:"backend,omitempty"`
-
-	Hostname string `json:"hostname,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Backend") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Backend") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesAckRequest) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesAckRequest
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesPollRequest: Represents a request
-// to poll for instructions given to a machine.
-type ComponentsMachineProviderRpcMessagesPollRequest struct {
-	// Possible values:
-	//   "DUMMY"
-	//   "GCE"
-	//   "VSPHERE"
-	Backend string `json:"backend,omitempty"`
-
-	Hostname string `json:"hostname,omitempty"`
-
-	// ForceSendFields is a list of field names (e.g. "Backend") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Backend") to include in
-	// API requests with the JSON null value. By default, fields with empty
-	// values are omitted from API requests. However, any field with an
-	// empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesPollRequest) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesPollRequest
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// ComponentsMachineProviderRpcMessagesPollResponse: Represents a
-// response to a request for instructions given to a machine.
-type ComponentsMachineProviderRpcMessagesPollResponse struct {
-	// Instruction: Represents instructions for a machine.
-	Instruction *ComponentsMachineProviderInstructionsInstruction `json:"instruction,omitempty"`
-
-	State string `json:"state,omitempty"`
-
-	// ServerResponse contains the HTTP response code and headers from the
-	// server.
-	googleapi.ServerResponse `json:"-"`
-
-	// ForceSendFields is a list of field names (e.g. "Instruction") to
-	// unconditionally include in API requests. By default, fields with
-	// empty values are omitted from API requests. However, any non-pointer,
-	// non-interface field appearing in ForceSendFields will be sent to the
-	// server regardless of whether the field is empty or not. This may be
-	// used to include empty fields in Patch requests.
-	ForceSendFields []string `json:"-"`
-
-	// NullFields is a list of field names (e.g. "Instruction") to include
-	// in API requests with the JSON null value. By default, fields with
-	// empty values are omitted from API requests. However, any field with
-	// an empty value appearing in NullFields will be sent to the server as
-	// null. It is an error if a field in this list has a non-empty value.
-	// This may be used to include null fields in Patch requests.
-	NullFields []string `json:"-"`
-}
-
-func (s *ComponentsMachineProviderRpcMessagesPollResponse) MarshalJSON() ([]byte, error) {
-	type NoMethod ComponentsMachineProviderRpcMessagesPollResponse
-	raw := NoMethod(*s)
-	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
-}
-
-// method id "machine.ack":
-
-type AckCall struct {
-	s                                              *Service
-	componentsmachineproviderrpcmessagesackrequest *ComponentsMachineProviderRpcMessagesAckRequest
-	urlParams_                                     gensupport.URLParams
-	ctx_                                           context.Context
-	header_                                        http.Header
-}
-
-// Ack: Handles an incoming AckRequest.
-func (s *Service) Ack(componentsmachineproviderrpcmessagesackrequest *ComponentsMachineProviderRpcMessagesAckRequest) *AckCall {
-	c := &AckCall{s: s, urlParams_: make(gensupport.URLParams)}
-	c.componentsmachineproviderrpcmessagesackrequest = componentsmachineproviderrpcmessagesackrequest
-	return c
-}
-
-// Fields allows partial responses to be retrieved. See
-// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
-// for more information.
-func (c *AckCall) Fields(s ...googleapi.Field) *AckCall {
-	c.urlParams_.Set("fields", googleapi.CombineFields(s))
-	return c
-}
-
-// Context sets the context to be used in this call's Do method. Any
-// pending HTTP request will be aborted if the provided context is
-// canceled.
-func (c *AckCall) Context(ctx context.Context) *AckCall {
-	c.ctx_ = ctx
-	return c
-}
-
-// Header returns an http.Header that can be modified by the caller to
-// add HTTP headers to the request.
-func (c *AckCall) Header() http.Header {
-	if c.header_ == nil {
-		c.header_ = make(http.Header)
-	}
-	return c.header_
-}
-
-func (c *AckCall) doRequest(alt string) (*http.Response, error) {
-	reqHeaders := make(http.Header)
-	for k, v := range c.header_ {
-		reqHeaders[k] = v
-	}
-	reqHeaders.Set("User-Agent", c.s.userAgent())
-	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.componentsmachineproviderrpcmessagesackrequest)
-	if err != nil {
-		return nil, err
-	}
-	reqHeaders.Set("Content-Type", "application/json")
-	c.urlParams_.Set("alt", alt)
-	c.urlParams_.Set("prettyPrint", "false")
-	urls := googleapi.ResolveRelative(c.s.BasePath, "ack")
-	urls += "?" + c.urlParams_.Encode()
-	req, err := http.NewRequest("POST", urls, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header = reqHeaders
-	return gensupport.SendRequest(c.ctx_, c.s.client, req)
-}
-
-// Do executes the "machine.ack" call.
-func (c *AckCall) Do(opts ...googleapi.CallOption) error {
-	gensupport.SetOptions(c.urlParams_, opts...)
-	res, err := c.doRequest("json")
-	if err != nil {
-		return err
-	}
-	defer googleapi.CloseBody(res)
-	if err := googleapi.CheckResponse(res); err != nil {
-		return err
-	}
-	return nil
-	// {
-	//   "description": "Handles an incoming AckRequest.",
-	//   "httpMethod": "POST",
-	//   "id": "machine.ack",
-	//   "path": "ack",
-	//   "request": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesAckRequest",
-	//     "parameterName": "resource"
-	//   },
-	//   "scopes": [
-	//     "https://www.googleapis.com/auth/userinfo.email"
-	//   ]
-	// }
-
-}
-
-// method id "machine.poll":
-
-type PollCall struct {
-	s                                               *Service
-	componentsmachineproviderrpcmessagespollrequest *ComponentsMachineProviderRpcMessagesPollRequest
-	urlParams_                                      gensupport.URLParams
-	ctx_                                            context.Context
-	header_                                         http.Header
-}
-
-// Poll: Handles an incoming PollRequest.
-func (s *Service) Poll(componentsmachineproviderrpcmessagespollrequest *ComponentsMachineProviderRpcMessagesPollRequest) *PollCall {
-	c := &PollCall{s: s, urlParams_: make(gensupport.URLParams)}
-	c.componentsmachineproviderrpcmessagespollrequest = componentsmachineproviderrpcmessagespollrequest
-	return c
-}
-
-// Fields allows partial responses to be retrieved. See
-// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
-// for more information.
-func (c *PollCall) Fields(s ...googleapi.Field) *PollCall {
-	c.urlParams_.Set("fields", googleapi.CombineFields(s))
-	return c
-}
-
-// Context sets the context to be used in this call's Do method. Any
-// pending HTTP request will be aborted if the provided context is
-// canceled.
-func (c *PollCall) Context(ctx context.Context) *PollCall {
-	c.ctx_ = ctx
-	return c
-}
-
-// Header returns an http.Header that can be modified by the caller to
-// add HTTP headers to the request.
-func (c *PollCall) Header() http.Header {
-	if c.header_ == nil {
-		c.header_ = make(http.Header)
-	}
-	return c.header_
-}
-
-func (c *PollCall) doRequest(alt string) (*http.Response, error) {
-	reqHeaders := make(http.Header)
-	for k, v := range c.header_ {
-		reqHeaders[k] = v
-	}
-	reqHeaders.Set("User-Agent", c.s.userAgent())
-	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.componentsmachineproviderrpcmessagespollrequest)
-	if err != nil {
-		return nil, err
-	}
-	reqHeaders.Set("Content-Type", "application/json")
-	c.urlParams_.Set("alt", alt)
-	c.urlParams_.Set("prettyPrint", "false")
-	urls := googleapi.ResolveRelative(c.s.BasePath, "poll")
-	urls += "?" + c.urlParams_.Encode()
-	req, err := http.NewRequest("POST", urls, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header = reqHeaders
-	return gensupport.SendRequest(c.ctx_, c.s.client, req)
-}
-
-// Do executes the "machine.poll" call.
-// Exactly one of *ComponentsMachineProviderRpcMessagesPollResponse or
-// error will be non-nil. Any non-2xx status code is an error. Response
-// headers are in either
-// *ComponentsMachineProviderRpcMessagesPollResponse.ServerResponse.Heade
-// r or (if a response was returned at all) in
-// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
-// whether the returned error was because http.StatusNotModified was
-// returned.
-func (c *PollCall) Do(opts ...googleapi.CallOption) (*ComponentsMachineProviderRpcMessagesPollResponse, error) {
-	gensupport.SetOptions(c.urlParams_, opts...)
-	res, err := c.doRequest("json")
-	if res != nil && res.StatusCode == http.StatusNotModified {
-		if res.Body != nil {
-			res.Body.Close()
-		}
-		return nil, &googleapi.Error{
-			Code:   res.StatusCode,
-			Header: res.Header,
-		}
-	}
-	if err != nil {
-		return nil, err
-	}
-	defer googleapi.CloseBody(res)
-	if err := googleapi.CheckResponse(res); err != nil {
-		return nil, err
-	}
-	ret := &ComponentsMachineProviderRpcMessagesPollResponse{
-		ServerResponse: googleapi.ServerResponse{
-			Header:         res.Header,
-			HTTPStatusCode: res.StatusCode,
-		},
-	}
-	target := &ret
-	if err := gensupport.DecodeResponse(target, res); err != nil {
-		return nil, err
-	}
-	return ret, nil
-	// {
-	//   "description": "Handles an incoming PollRequest.",
-	//   "httpMethod": "POST",
-	//   "id": "machine.poll",
-	//   "path": "poll",
-	//   "request": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesPollRequest",
-	//     "parameterName": "resource"
-	//   },
-	//   "response": {
-	//     "$ref": "ComponentsMachineProviderRpcMessagesPollResponse"
-	//   },
-	//   "scopes": [
-	//     "https://www.googleapis.com/auth/userinfo.email"
-	//   ]
-	// }
-
-}
diff --git a/mp/README.md b/mp/README.md
deleted file mode 100644
index fde6d39..0000000
--- a/mp/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Machine Provider
-
-[Machine Provider] is a service which provides machines using a leasing
-mechanism.
-
-[Machine Provider]: https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/machine_provider
diff --git a/mp/cmd/mpagent/README.md b/mp/cmd/mpagent/README.md
deleted file mode 100644
index 33ec9ab..0000000
--- a/mp/cmd/mpagent/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Machine Provider Agent
-
-The [Machine Provider] agent is a package which runs on a machine in order to
-communicate with the Machine Provider server.
-
-The agent is recommended to be built as a [CIPD] package. Deployment to machines
-is left to the user.
-
-[CIPD]: https://chromium.googlesource.com/infra/luci/luci-go/+/master/cipd
-[Machine Provider]: https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/machine_provider
diff --git a/mp/cmd/mpagent/agent_darwin.go b/mp/cmd/mpagent/agent_darwin.go
deleted file mode 100644
index 3d081f9..0000000
--- a/mp/cmd/mpagent/agent_darwin.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"context"
-
-	"go.chromium.org/luci/common/errors"
-)
-
-// getAgent returns an agent which runs on Mac OS.
-func getAgent(ctx context.Context) (*Agent, error) {
-	return nil, errors.New("unsupported platform, expected Linux or Windows")
-}
diff --git a/mp/cmd/mpagent/agent_linux.go b/mp/cmd/mpagent/agent_linux.go
deleted file mode 100644
index 91be1fb..0000000
--- a/mp/cmd/mpagent/agent_linux.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"bufio"
-	"context"
-	"fmt"
-	"io"
-	"os"
-	"os/exec"
-	"os/user"
-	"strconv"
-	"strings"
-	"syscall"
-	"time"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-)
-
-type LinuxStrategy struct {
-}
-
-// chown changes ownership of a path.
-func (LinuxStrategy) chown(ctx context.Context, username, path string) error {
-	user, err := user.Lookup(username)
-	if err != nil {
-		return err
-	}
-	uid, err := strconv.Atoi(user.Uid)
-	if err != nil {
-		return err
-	}
-	gid, err := strconv.Atoi(user.Gid)
-	if err != nil {
-		return err
-	}
-	return os.Chown(path, uid, gid)
-}
-
-// configureAutoMount mounts the specified disk and configures mount on startup.
-//
-// Assumes the disk is already formatted as ext4.
-func (LinuxStrategy) configureAutoMount(ctx context.Context, disk string) error {
-	// Wait for the disk to be attached.
-	for {
-		err := exec.Command("blkid", disk).Run()
-		if err == nil {
-			logging.Infof(ctx, "Attached: %s.", disk)
-			break
-		}
-		s := err.(*exec.ExitError).Sys().(syscall.WaitStatus)
-		if s.ExitStatus() != 2 {
-			// 2 means the specified device wasn't found.
-			// Keep waiting if 2, otherwise return an error.
-			return err
-		}
-		time.Sleep(60 * time.Second)
-		logging.Infof(ctx, "Waiting for disk to be attached...")
-	}
-	// Configure auto-mount using fstab.
-	f, err := os.OpenFile("/etc/fstab", os.O_RDWR, 0)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-	scanner := bufio.NewScanner(f)
-	for scanner.Scan() {
-		if strings.Contains(scanner.Text(), disk) {
-			logging.Infof(ctx, "Already mounted: %s.", disk)
-			return nil
-		}
-	}
-	logging.Infof(ctx, "Mounting: %s.", disk)
-	// Ensure the cursor is at the end so the new line is appended.
-	f.Seek(0, io.SeekEnd)
-	line := []byte(fmt.Sprintf("%s /b ext4 defaults,nobootwait,nofail 0 2\n", disk))
-	if _, err := f.Write(line); err != nil {
-		return err
-	}
-	// Ensure the file is closed before mount reads from it.
-	f.Close()
-	return exec.Command("/bin/mount", "--all").Run()
-}
-
-// reboot reboots the machine.
-func (LinuxStrategy) reboot(ctx context.Context) error {
-	return exec.Command("/sbin/shutdown", "-r", "now").Run()
-}
-
-type SystemdStrategy struct {
-	LinuxStrategy
-}
-
-// enableSwarming enables installed service.
-func (SystemdStrategy) enableSwarming(ctx context.Context) error {
-	if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
-		return err
-	}
-	return exec.Command("systemctl", "enable", "swarming-start-bot").Run()
-}
-
-// start starts the agent.
-func (SystemdStrategy) start(ctx context.Context, _ string) error {
-	if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
-		return err
-	}
-	if err := exec.Command("systemctl", "enable", "machine-provider-agent").Run(); err != nil {
-		return err
-	}
-	return exec.Command("systemctl", "start", "machine-provider-agent").Run()
-}
-
-// stop stops all instances of the agent.
-func (SystemdStrategy) stop(ctx context.Context) error {
-	return exec.Command("systemctl", "stop", "machine-provider-agent").Run()
-}
-
-type UpstartStrategy struct {
-	LinuxStrategy
-}
-
-// enableSwarming enables installed service.
-func (UpstartStrategy) enableSwarming(ctx context.Context) error {
-	return nil
-}
-
-// start starts the agent.
-func (UpstartStrategy) start(ctx context.Context, _ string) error {
-	if err := exec.Command("initctl", "reload-configuration").Run(); err != nil {
-		return err
-	}
-	return exec.Command("start", "machine-provider-agent").Run()
-}
-
-// stop stops all instances of the agent.
-func (UpstartStrategy) stop(ctx context.Context) error {
-	return exec.Command("stop", "machine-provider-agent").Run()
-}
-
-// systemdFound returns true iff systemd is supported on this machine.
-func systemdFound() bool {
-	return exec.Command("which", "systemctl").Run() == nil
-}
-
-// upstartFound returns true iff upstart is supported on this machine.
-func upstartFound() bool {
-	return exec.Command("init", "--version").Run() == nil
-}
-
-// getAgent returns an agent which runs on Linux, depending on supported init systems.
-func getAgent(ctx context.Context) (*Agent, error) {
-	if systemdFound() {
-		agent := Agent{
-			agentAutoStartPath:        "/etc/systemd/system/machine-provider-agent.service",
-			agentAutoStartTemplate:    "machine-provider-agent.service.tmpl",
-			logsDir:                   "/var/log/machine-provider-agent",
-			swarmingAutoStartPath:     "/etc/systemd/system/swarming-start-bot.service",
-			swarmingAutoStartTemplate: "swarming-start-bot.service.tmpl",
-			swarmingBotDir:            "/b/s",
-			strategy:                  SystemdStrategy{},
-		}
-		logging.Infof(ctx, "Using systemd Linux agent.")
-		return &agent, nil
-	}
-
-	if upstartFound() {
-		agent := Agent{
-			agentAutoStartPath:        "/etc/init/machine-provider-agent.conf",
-			agentAutoStartTemplate:    "machine-provider-agent.conf.tmpl",
-			logsDir:                   "/var/log/messages/machine-provider-agent",
-			swarmingAutoStartPath:     "/etc/init/swarming-start-bot.conf",
-			swarmingAutoStartTemplate: "swarming-start-bot.conf.tmpl",
-			swarmingBotDir:            "/b/s",
-			strategy:                  UpstartStrategy{},
-		}
-		logging.Infof(ctx, "Using Upstart Linux agent.")
-		return &agent, nil
-	}
-
-	return nil, errors.New("unsupported init system, expected systemd or Upstart")
-}
diff --git a/mp/cmd/mpagent/agent_windows.go b/mp/cmd/mpagent/agent_windows.go
deleted file mode 100644
index fdda5f7..0000000
--- a/mp/cmd/mpagent/agent_windows.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"context"
-	"os/exec"
-	"syscall"
-
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-)
-
-type WindowsStrategy struct {
-}
-
-// chown changes ownership of a path.
-func (WindowsStrategy) chown(ctx context.Context, username, path string) error {
-	// TODO(smut): Determine if this is necessary on Windows.
-	return nil
-}
-
-// enableSwarming enables installed service.
-func (WindowsStrategy) enableSwarming(ctx context.Context) error {
-	return nil
-}
-
-// configureAutoMount mounts the specified disk and configures mount on startup.
-//
-// Assumes the disk is already formatted as ntfs.
-func (WindowsStrategy) configureAutoMount(ctx context.Context, disk string) error {
-	// TODO(smut): Mount the specified disk.
-	return errors.New("mounting disks is unsupported on Windows")
-}
-
-// reboot reboots the machine.
-func (WindowsStrategy) reboot(ctx context.Context) error {
-	return exec.Command("shutdown", "/f", "/r", "/t", "0").Run()
-}
-
-// start starts the agent.
-func (WindowsStrategy) start(ctx context.Context, path string) error {
-	cmd := exec.Command(path)
-	cmd.SysProcAttr = &syscall.SysProcAttr{
-		// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
-		// CREATE_NEW_PROCESS_GROUP: 	0x200
-		// DETACHED_PROCESS: 		0x008
-		CreationFlags: 0x200 | 0x8,
-	}
-	return cmd.Start()
-}
-
-// stop stops all instances of the agent.
-func (WindowsStrategy) stop(ctx context.Context) error {
-	// TODO(smut): Stop the agent.
-	return nil
-}
-
-// getAgent returns an agent which runs on Windows.
-func getAgent(ctx context.Context) (*Agent, error) {
-	agent := Agent{
-		agentAutoStartPath:        "C:\\Users\\{{.User}}\\Start Menu\\Programs\\Startup\\machine-provider-agent.bat",
-		agentAutoStartTemplate:    "machine-provider-agent.bat.tmpl",
-		logsDir:                   "C:\\logs",
-		swarmingAutoStartPath:     "C:\\Users\\{{.User}}\\Start Menu\\Programs\\Startup\\swarming-start-bot.bat",
-		swarmingAutoStartTemplate: "swarming-start-bot.bat.tmpl",
-		swarmingBotDir:            "C:\\b\\s",
-		strategy:                  WindowsStrategy{},
-	}
-	logging.Infof(ctx, "Using Windows agent.")
-	return &agent, nil
-}
diff --git a/mp/cmd/mpagent/assets.gen.go b/mp/cmd/mpagent/assets.gen.go
deleted file mode 100644
index a38dd45..0000000
--- a/mp/cmd/mpagent/assets.gen.go
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// AUTOGENERATED. DO NOT EDIT.
-
-// Package main is generated by go.chromium.org/luci/tools/cmd/assets.
-//
-// It contains all [*.css *.html *.js *.tmpl] files found in the package as byte arrays.
-package main
-
-// GetAsset returns an asset by its name. Returns nil if no such asset exists.
-func GetAsset(name string) []byte {
-	return []byte(files[name])
-}
-
-// GetAssetString is version of GetAsset that returns string instead of byte
-// slice. Returns empty string if no such asset exists.
-func GetAssetString(name string) string {
-	return files[name]
-}
-
-// GetAssetSHA256 returns the asset checksum. Returns nil if no such asset
-// exists.
-func GetAssetSHA256(name string) []byte {
-	data := fileSha256s[name]
-	if data == nil {
-		return nil
-	}
-	return append([]byte(nil), data...)
-}
-
-// Assets returns a map of all assets.
-func Assets() map[string]string {
-	cpy := make(map[string]string, len(files))
-	for k, v := range files {
-		cpy[k] = v
-	}
-	return cpy
-}
-
-var files = map[string]string{
-	"machine-provider-agent.bat.tmpl": string([]byte{58, 58,
-		32, 109, 97, 99, 104, 105, 110, 101, 45, 112, 114, 111, 118, 105,
-		100, 101, 114, 45, 97, 103, 101, 110, 116, 10, 58, 58, 10, 58,
-		58, 32, 82, 117, 110, 115, 32, 116, 104, 101, 32, 77, 97, 99,
-		104, 105, 110, 101, 32, 80, 114, 111, 118, 105, 100, 101, 114, 32,
-		97, 103, 101, 110, 116, 32, 112, 114, 111, 99, 101, 115, 115, 46,
-		10, 10, 64, 123, 123, 46, 65, 103, 101, 110, 116, 125, 125, 32,
-		45, 103, 99, 101, 45, 115, 101, 114, 118, 105, 99, 101, 45, 97,
-		99, 99, 111, 117, 110, 116, 32, 123, 123, 46, 83, 101, 114, 118,
-		105, 99, 101, 65, 99, 99, 111, 117, 110, 116, 125, 125, 32, 45,
-		115, 101, 114, 118, 101, 114, 32, 123, 123, 46, 83, 101, 114, 118,
-		101, 114, 125, 125, 32, 45, 117, 115, 101, 114, 32, 123, 123, 46,
-		85, 115, 101, 114, 125, 125, 10}),
-	"machine-provider-agent.conf.tmpl": string([]byte{35, 32,
-		109, 97, 99, 104, 105, 110, 101, 45, 112, 114, 111, 118, 105, 100,
-		101, 114, 45, 97, 103, 101, 110, 116, 10, 35, 10, 35, 32, 82,
-		117, 110, 115, 32, 116, 104, 101, 32, 77, 97, 99, 104, 105, 110,
-		101, 32, 80, 114, 111, 118, 105, 100, 101, 114, 32, 97, 103, 101,
-		110, 116, 32, 112, 114, 111, 99, 101, 115, 115, 46, 10, 10, 100,
-		101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 32, 34, 109, 97,
-		99, 104, 105, 110, 101, 32, 112, 114, 111, 118, 105, 100, 101, 114,
-		32, 97, 103, 101, 110, 116, 34, 10, 10, 115, 116, 97, 114, 116,
-		32, 111, 110, 32, 40, 102, 105, 108, 101, 115, 121, 115, 116, 101,
-		109, 32, 97, 110, 100, 32, 110, 101, 116, 45, 100, 101, 118, 105,
-		99, 101, 45, 117, 112, 32, 73, 70, 65, 67, 69, 33, 61, 108,
-		111, 41, 10, 115, 116, 111, 112, 32, 111, 110, 32, 115, 104, 117,
-		116, 100, 111, 119, 110, 10, 10, 115, 99, 114, 105, 112, 116, 10,
-		32, 32, 123, 123, 46, 65, 103, 101, 110, 116, 125, 125, 32, 45,
-		103, 99, 101, 45, 115, 101, 114, 118, 105, 99, 101, 45, 97, 99,
-		99, 111, 117, 110, 116, 32, 123, 123, 46, 83, 101, 114, 118, 105,
-		99, 101, 65, 99, 99, 111, 117, 110, 116, 125, 125, 32, 45, 115,
-		101, 114, 118, 101, 114, 32, 123, 123, 46, 83, 101, 114, 118, 101,
-		114, 125, 125, 32, 45, 117, 115, 101, 114, 32, 123, 123, 46, 85,
-		115, 101, 114, 125, 125, 10, 101, 110, 100, 32, 115, 99, 114, 105,
-		112, 116, 10, 10, 114, 101, 115, 112, 97, 119, 110, 10, 114, 101,
-		115, 112, 97, 119, 110, 32, 108, 105, 109, 105, 116, 32, 117, 110,
-		108, 105, 109, 105, 116, 101, 100, 10, 10, 112, 111, 115, 116, 45,
-		115, 116, 111, 112, 32, 101, 120, 101, 99, 32, 115, 108, 101, 101,
-		112, 32, 53, 10}),
-	"machine-provider-agent.service.tmpl": string([]byte{91, 85,
-		110, 105, 116, 93, 10, 68, 101, 115, 99, 114, 105, 112, 116, 105,
-		111, 110, 61, 77, 97, 99, 104, 105, 110, 101, 32, 80, 114, 111,
-		118, 105, 100, 101, 114, 32, 97, 103, 101, 110, 116, 10, 65, 102,
-		116, 101, 114, 61, 110, 101, 116, 119, 111, 114, 107, 46, 116, 97,
-		114, 103, 101, 116, 10, 10, 91, 83, 101, 114, 118, 105, 99, 101,
-		93, 10, 84, 121, 112, 101, 61, 115, 105, 109, 112, 108, 101, 10,
-		82, 101, 115, 116, 97, 114, 116, 61, 97, 108, 119, 97, 121, 115,
-		10, 82, 101, 115, 116, 97, 114, 116, 83, 101, 99, 61, 53, 10,
-		69, 120, 101, 99, 83, 116, 97, 114, 116, 61, 123, 123, 46, 65,
-		103, 101, 110, 116, 125, 125, 32, 45, 103, 99, 101, 45, 115, 101,
-		114, 118, 105, 99, 101, 45, 97, 99, 99, 111, 117, 110, 116, 32,
-		123, 123, 46, 83, 101, 114, 118, 105, 99, 101, 65, 99, 99, 111,
-		117, 110, 116, 125, 125, 32, 45, 115, 101, 114, 118, 101, 114, 32,
-		123, 123, 46, 83, 101, 114, 118, 101, 114, 125, 125, 32, 45, 117,
-		115, 101, 114, 32, 123, 123, 46, 85, 115, 101, 114, 125, 125, 10,
-		10, 91, 73, 110, 115, 116, 97, 108, 108, 93, 10, 87, 97, 110,
-		116, 101, 100, 66, 121, 61, 109, 117, 108, 116, 105, 45, 117, 115,
-		101, 114, 46, 116, 97, 114, 103, 101, 116, 10}),
-	"swarming-start-bot.bat.tmpl": string([]byte{58, 58,
-		32, 115, 119, 97, 114, 109, 105, 110, 103, 45, 115, 116, 97, 114,
-		116, 45, 98, 111, 116, 32, 45, 32, 115, 119, 97, 114, 109, 105,
-		110, 103, 32, 98, 111, 116, 32, 115, 116, 97, 114, 116, 117, 112,
-		10, 58, 58, 10, 58, 58, 32, 85, 115, 101, 100, 32, 102, 111,
-		114, 32, 115, 116, 97, 114, 116, 105, 110, 103, 32, 97, 32, 83,
-		119, 97, 114, 109, 105, 110, 103, 32, 98, 111, 116, 32, 112, 114,
-		111, 99, 101, 115, 115, 46, 10, 10, 58, 58, 32, 80, 114, 101,
-		118, 101, 110, 116, 32, 83, 119, 97, 114, 109, 105, 110, 103, 32,
-		102, 114, 111, 109, 32, 99, 111, 110, 102, 105, 103, 117, 114, 105,
-		110, 103, 32, 105, 116, 115, 32, 111, 119, 110, 32, 97, 117, 116,
-		111, 115, 116, 97, 114, 116, 46, 10, 83, 69, 84, 32, 83, 87,
-		65, 82, 77, 73, 78, 71, 95, 69, 88, 84, 69, 82, 78, 65,
-		76, 95, 66, 79, 84, 95, 83, 69, 84, 85, 80, 61, 49, 10,
-		64, 67, 58, 92, 116, 111, 111, 108, 115, 92, 112, 121, 116, 104,
-		111, 110, 92, 98, 105, 110, 92, 112, 121, 116, 104, 111, 110, 46,
-		101, 120, 101, 32, 123, 123, 46, 80, 97, 116, 104, 125, 125, 32,
-		115, 116, 97, 114, 116, 95, 98, 111, 116, 10}),
-	"swarming-start-bot.conf.tmpl": string([]byte{35, 32,
-		115, 119, 97, 114, 109, 105, 110, 103, 45, 115, 116, 97, 114, 116,
-		45, 98, 111, 116, 32, 45, 32, 115, 119, 97, 114, 109, 105, 110,
-		103, 32, 98, 111, 116, 32, 115, 116, 97, 114, 116, 117, 112, 10,
-		35, 10, 35, 32, 85, 115, 101, 100, 32, 102, 111, 114, 32, 115,
-		116, 97, 114, 116, 105, 110, 103, 32, 97, 32, 83, 119, 97, 114,
-		109, 105, 110, 103, 32, 98, 111, 116, 32, 112, 114, 111, 99, 101,
-		115, 115, 46, 10, 10, 100, 101, 115, 99, 114, 105, 112, 116, 105,
-		111, 110, 32, 34, 115, 119, 97, 114, 109, 105, 110, 103, 32, 98,
-		111, 116, 32, 115, 116, 97, 114, 116, 117, 112, 34, 10, 10, 115,
-		116, 97, 114, 116, 32, 111, 110, 32, 40, 102, 105, 108, 101, 115,
-		121, 115, 116, 101, 109, 32, 97, 110, 100, 32, 110, 101, 116, 45,
-		100, 101, 118, 105, 99, 101, 45, 117, 112, 32, 73, 70, 65, 67,
-		69, 33, 61, 108, 111, 41, 10, 115, 116, 111, 112, 32, 111, 110,
-		32, 115, 104, 117, 116, 100, 111, 119, 110, 10, 108, 105, 109, 105,
-		116, 32, 110, 111, 102, 105, 108, 101, 32, 53, 48, 48, 48, 48,
-		32, 53, 48, 48, 48, 48, 10, 10, 115, 99, 114, 105, 112, 116,
-		10, 32, 32, 47, 117, 115, 114, 47, 98, 105, 110, 47, 115, 117,
-		100, 111, 32, 45, 72, 32, 45, 117, 32, 123, 123, 46, 85, 115,
-		101, 114, 125, 125, 32, 83, 87, 65, 82, 77, 73, 78, 71, 95,
-		69, 88, 84, 69, 82, 78, 65, 76, 95, 66, 79, 84, 95, 83,
-		69, 84, 85, 80, 61, 49, 32, 47, 117, 115, 114, 47, 98, 105,
-		110, 47, 112, 121, 116, 104, 111, 110, 32, 123, 123, 46, 80, 97,
-		116, 104, 125, 125, 32, 115, 116, 97, 114, 116, 95, 98, 111, 116,
-		10, 101, 110, 100, 32, 115, 99, 114, 105, 112, 116, 10}),
-	"swarming-start-bot.service.tmpl": string([]byte{91, 85,
-		110, 105, 116, 93, 10, 68, 101, 115, 99, 114, 105, 112, 116, 105,
-		111, 110, 61, 83, 119, 97, 114, 109, 105, 110, 103, 32, 98, 111,
-		116, 32, 115, 116, 97, 114, 116, 117, 112, 10, 65, 102, 116, 101,
-		114, 61, 110, 101, 116, 119, 111, 114, 107, 46, 116, 97, 114, 103,
-		101, 116, 10, 10, 91, 83, 101, 114, 118, 105, 99, 101, 93, 10,
-		84, 121, 112, 101, 61, 115, 105, 109, 112, 108, 101, 10, 85, 115,
-		101, 114, 61, 123, 123, 46, 85, 115, 101, 114, 125, 125, 10, 76,
-		105, 109, 105, 116, 78, 79, 70, 73, 76, 69, 61, 53, 48, 48,
-		48, 48, 10, 69, 110, 118, 105, 114, 111, 110, 109, 101, 110, 116,
-		61, 83, 87, 65, 82, 77, 73, 78, 71, 95, 69, 88, 84, 69,
-		82, 78, 65, 76, 95, 66, 79, 84, 95, 83, 69, 84, 85, 80,
-		61, 49, 10, 69, 120, 101, 99, 83, 116, 97, 114, 116, 61, 47,
-		117, 115, 114, 47, 98, 105, 110, 47, 112, 121, 116, 104, 111, 110,
-		32, 123, 123, 46, 80, 97, 116, 104, 125, 125, 32, 115, 116, 97,
-		114, 116, 95, 98, 111, 116, 10, 10, 91, 73, 110, 115, 116, 97,
-		108, 108, 93, 10, 87, 97, 110, 116, 101, 100, 66, 121, 61, 109,
-		117, 108, 116, 105, 45, 117, 115, 101, 114, 46, 116, 97, 114, 103,
-		101, 116, 10}),
-}
-
-var fileSha256s = map[string][]byte{
-	"machine-provider-agent.bat.tmpl": {125, 73,
-		232, 119, 61, 107, 159, 152, 105, 88, 23, 239, 10, 24, 85, 68,
-		59, 36, 105, 114, 195, 228, 186, 115, 85, 238, 180, 117, 224, 170,
-		14, 199},
-	"machine-provider-agent.conf.tmpl": {71, 237,
-		73, 176, 85, 229, 154, 146, 140, 247, 128, 215, 158, 161, 19, 232,
-		215, 97, 195, 187, 118, 146, 142, 22, 238, 206, 193, 180, 34, 13,
-		214, 100},
-	"machine-provider-agent.service.tmpl": {228, 23,
-		38, 10, 145, 147, 50, 183, 167, 180, 244, 49, 230, 17, 98, 242,
-		218, 68, 39, 78, 221, 199, 141, 24, 242, 67, 73, 92, 167, 222,
-		8, 43},
-	"swarming-start-bot.bat.tmpl": {223, 155,
-		52, 23, 163, 162, 69, 31, 35, 140, 191, 28, 4, 51, 228, 141,
-		7, 182, 247, 255, 182, 222, 218, 80, 171, 191, 144, 114, 152, 108,
-		186, 166},
-	"swarming-start-bot.conf.tmpl": {140, 14,
-		119, 253, 173, 199, 208, 81, 209, 221, 4, 185, 142, 240, 103, 82,
-		120, 27, 129, 250, 73, 231, 206, 205, 134, 32, 50, 3, 219, 237,
-		214, 191},
-	"swarming-start-bot.service.tmpl": {184, 229,
-		46, 51, 171, 238, 112, 15, 28, 29, 134, 232, 200, 215, 231, 149,
-		71, 227, 141, 211, 15, 242, 245, 204, 250, 116, 88, 179, 110, 123,
-		60, 138},
-}
diff --git a/mp/cmd/mpagent/assets_test.go b/mp/cmd/mpagent/assets_test.go
deleted file mode 100644
index 68bf53b..0000000
--- a/mp/cmd/mpagent/assets_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// AUTOGENERATED. DO NOT EDIT.
-
-// This file is generated by go.chromium.org/luci/tools/cmd/assets.
-//
-// It contains tests that ensure that assets embedded into the binary are
-// identical to files on disk.
-
-package main
-
-import (
-	"go/build"
-	"io/ioutil"
-	"path/filepath"
-	"testing"
-)
-
-func TestAssets(t *testing.T) {
-	t.Parallel()
-
-	pkg, err := build.ImportDir(".", build.FindOnly)
-	if err != nil {
-		t.Fatalf("can't load package: %s", err)
-	}
-
-	fail := false
-	for name := range Assets() {
-		GetAsset(name) // for code coverage
-		path := filepath.Join(pkg.Dir, filepath.FromSlash(name))
-		blob, err := ioutil.ReadFile(path)
-		if err != nil {
-			t.Errorf("can't read file with assets %q (%s) - %s", name, path, err)
-			fail = true
-		} else if string(blob) != GetAssetString(name) {
-			t.Errorf("embedded asset %q is out of date", name)
-			fail = true
-		}
-	}
-
-	if fail {
-		t.Fatalf("run 'go generate' to update assets.gen.go")
-	}
-}
diff --git a/mp/cmd/mpagent/generate.go b/mp/cmd/mpagent/generate.go
deleted file mode 100644
index e07475f..0000000
--- a/mp/cmd/mpagent/generate.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//go:generate go install go.chromium.org/luci/tools/cmd/assets
-//go:generate assets
-
-package main
diff --git a/mp/cmd/mpagent/machine-provider-agent.bat.tmpl b/mp/cmd/mpagent/machine-provider-agent.bat.tmpl
deleted file mode 100644
index e5b9371..0000000
--- a/mp/cmd/mpagent/machine-provider-agent.bat.tmpl
+++ /dev/null
@@ -1,5 +0,0 @@
-:: machine-provider-agent
-::
-:: Runs the Machine Provider agent process.
-
-@{{.Agent}} -gce-service-account {{.ServiceAccount}} -server {{.Server}} -user {{.User}}
diff --git a/mp/cmd/mpagent/machine-provider-agent.conf.tmpl b/mp/cmd/mpagent/machine-provider-agent.conf.tmpl
deleted file mode 100644
index 3d4b353..0000000
--- a/mp/cmd/mpagent/machine-provider-agent.conf.tmpl
+++ /dev/null
@@ -1,17 +0,0 @@
-# machine-provider-agent
-#
-# Runs the Machine Provider agent process.
-
-description "machine provider agent"
-
-start on (filesystem and net-device-up IFACE!=lo)
-stop on shutdown
-
-script
-  {{.Agent}} -gce-service-account {{.ServiceAccount}} -server {{.Server}} -user {{.User}}
-end script
-
-respawn
-respawn limit unlimited
-
-post-stop exec sleep 5
diff --git a/mp/cmd/mpagent/machine-provider-agent.service.tmpl b/mp/cmd/mpagent/machine-provider-agent.service.tmpl
deleted file mode 100644
index ab31c3b..0000000
--- a/mp/cmd/mpagent/machine-provider-agent.service.tmpl
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-Description=Machine Provider agent
-After=network.target
-
-[Service]
-Type=simple
-Restart=always
-RestartSec=5
-ExecStart={{.Agent}} -gce-service-account {{.ServiceAccount}} -server {{.Server}} -user {{.User}}
-
-[Install]
-WantedBy=multi-user.target
diff --git a/mp/cmd/mpagent/main.go b/mp/cmd/mpagent/main.go
deleted file mode 100644
index 7d6c51d..0000000
--- a/mp/cmd/mpagent/main.go
+++ /dev/null
@@ -1,411 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package main contains the Machine Provider Agent, a process which runs on
-// machines and communicates with the Machine Provider service.
-package main
-
-import (
-	"context"
-	"flag"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"path/filepath"
-	"strconv"
-	"time"
-
-	"cloud.google.com/go/compute/metadata"
-
-	"go.chromium.org/luci/auth"
-	machine "go.chromium.org/luci/common/api/machine_provider/machine/v1"
-	"go.chromium.org/luci/common/data/rand/mathrand"
-	"go.chromium.org/luci/common/errors"
-	"go.chromium.org/luci/common/logging"
-	"go.chromium.org/luci/common/logging/gologger"
-	"go.chromium.org/luci/common/logging/teelogger"
-	"go.chromium.org/luci/common/tsmon"
-)
-
-// Strategy is platform-specific agent implementation. See agent_*.go.
-type Strategy interface {
-	// chown changes ownership of a path.
-	chown(ctx context.Context, username, path string) error
-	// configureAutoMount mounts the specified disk and configures mount on startup.
-	configureAutoMount(ctx context.Context, disk string) error
-	// enableSwarming enables installed service.
-	enableSwarming(ctx context.Context) error
-	// start starts the agent.
-	start(ctx context.Context, path string) error
-	// stop stops all instances of the agent.
-	stop(ctx context.Context) error
-	// reboot reboots the machine.
-	reboot(ctx context.Context) error
-}
-
-type Agent struct {
-	// agentAutoStartPath is the path to install this agent's auto-start config to.
-	agentAutoStartPath string
-	// agentAutoStartTemplate is the name of the asset containing this agent's auto-start template.
-	agentAutoStartTemplate string
-	// client is the http.Client to use for HTTP requests.
-	client *http.Client
-	// hostname is the name of the host the agent is running on.
-	hostname string
-	// logsDir is the path to the directory where this agent should emit logging output.
-	logsDir string
-	// mp is the client to use to communicate with the Machine Provider server.
-	mp *MachineProvider
-	// server is the Machine Provider server to communicate with.
-	server string
-	// serviceAccount is the name of the service account to authenticate HTTP requests with.
-	serviceAccount string
-	// swarmingAutoStartPath is the path to install this agent's Swarming auto-start config to.
-	swarmingAutoStartPath string
-	// swarmingAutoStartTemplate is the name of the asset containing this agent's Swarming auto-start template.
-	swarmingAutoStartTemplate string
-	// swarmingBotDir is the directory where this agent should install the Swarming bot process.
-	swarmingBotDir string
-	// swarmingUser is the name of the user the agent should install Swarming for.
-	swarmingUser string
-	// strategy is the platform-specific implementation for this agent.
-	strategy Strategy
-}
-
-// configureAutoMount mounts the specified disk and configures mount on startup.
-//
-// Assumes the disk is already formatted correctly.
-func (agent *Agent) configureAutoMount(ctx context.Context, disk string) error {
-	return agent.strategy.configureAutoMount(ctx, disk)
-}
-
-// configureLogging configures logging to a file, in addition to any other logging.
-//
-// Returns modified context.Context.
-func (agent *Agent) configureLogging(ctx context.Context) (context.Context, error) {
-	log := fmt.Sprintf("agent.%s.log", strconv.FormatInt(time.Now().Unix(), 10))
-	if err := os.MkdirAll(agent.logsDir, 0755); err != nil {
-		return ctx, err
-	}
-
-	// TODO(smut): Capture logging emitted before configureLogging was called and
-	// write it to the log file.
-	out, err := os.OpenFile(filepath.Join(agent.logsDir, log), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
-	if err != nil {
-		return ctx, err
-	}
-	config := gologger.LoggerConfig{Out: out}
-	return teelogger.Use(ctx, config.NewLogger), nil
-}
-
-// configureMonitoring configures tsmon monitoring.
-func (agent *Agent) configureMonitoring(ctx context.Context) error {
-	flags := tsmon.NewFlags()
-	flags.Flush = "manual"
-	flags.Target.AutoGenHostname = true
-	flags.Target.TargetType = "task"
-	flags.Target.TaskJobName = "default"
-	flags.Target.TaskServiceName = "mpagent"
-	return tsmon.InitializeFromFlags(ctx, &flags)
-}
-
-// configureSwarmingAutoStart configures auto-connect to the given Swarming server on reboot.
-func (agent *Agent) configureSwarmingAutoStart(ctx context.Context, server string) error {
-	if err := os.MkdirAll(agent.swarmingBotDir, 0755); err != nil {
-		return err
-	}
-	if err := agent.strategy.chown(ctx, agent.swarmingUser, agent.swarmingBotDir); err != nil {
-		return err
-	}
-
-	path := filepath.Join(agent.swarmingBotDir, "swarming_bot.zip")
-	if err := agent.downloadSwarmingBotCode(ctx, server, path); err != nil {
-		return err
-	}
-
-	substitutions := map[string]string{
-		"Path": path,
-		"User": agent.swarmingUser,
-	}
-	content, err := substituteAsset(ctx, agent.swarmingAutoStartTemplate, substitutions)
-	if err != nil {
-		return err
-	}
-	path, err = substitute(ctx, agent.swarmingAutoStartPath, substitutions)
-	if err != nil {
-		return err
-	}
-	_, err = os.Stat(path)
-	switch {
-	case err == nil:
-		logging.Infof(ctx, "Reinstalling: %s.", path)
-	case os.IsNotExist(err):
-		logging.Infof(ctx, "Installing: %s.", path)
-	default:
-		return err
-	}
-	if err := ioutil.WriteFile(path, []byte(content), 0644); err != nil {
-		return err
-	}
-	return agent.strategy.enableSwarming(ctx)
-}
-
-// downloadSwarminBotCode downloads the Swarming bot code from the given server.
-func (agent *Agent) downloadSwarmingBotCode(ctx context.Context, server, path string) error {
-	_, err := os.Stat(path)
-	if err == nil {
-		logging.Infof(ctx, "Already installed: %s.", path)
-		return nil
-	}
-
-	logging.Infof(ctx, "Downloading: %s.", path)
-	response, err := agent.client.Get(server + "/bot_code")
-	if err != nil {
-		return err
-	}
-	defer response.Body.Close()
-	if response.StatusCode != 200 {
-		// TODO(smut): Differentiate between transient and non-transient.
-		return errors.New("unexpected HTTP status: " + response.Status)
-	}
-	out, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
-	if err != nil {
-		return err
-	}
-	defer out.Close()
-	_, err = io.Copy(out, response.Body)
-	if err != nil {
-		return err
-	}
-	return agent.strategy.chown(ctx, agent.swarmingUser, path)
-}
-
-// initialize initializes the agent.
-func (agent *Agent) initialize(ctx context.Context) (context.Context, error) {
-	ctx, err := agent.configureLogging(ctx)
-	if err != nil {
-		return ctx, err
-	}
-	if err = agent.configureMonitoring(ctx); err != nil {
-		return ctx, err
-	}
-
-	// TODO(smut): Remove fallback on metadata server.
-	if agent.server == "" {
-		agent.server, err = metadata.Get("instance/attributes/machine_provider_server")
-		if err != nil {
-			return ctx, err
-		}
-	}
-	if agent.serviceAccount == "" {
-		agent.serviceAccount, err = metadata.Get("instance/attributes/machine_service_account")
-		if err != nil {
-			return ctx, err
-		}
-	}
-
-	options := auth.Options{
-		GCEAccountName:         agent.serviceAccount,
-		ServiceAccountJSONPath: auth.GCEServiceAccount,
-	}
-	agent.client, err = auth.NewAuthenticator(ctx, auth.SilentLogin, options).Client()
-	if err != nil {
-		return ctx, err
-	}
-	metadataClient := metadata.NewClient(agent.client)
-	agent.hostname, err = metadataClient.InstanceName()
-	if err != nil {
-		return ctx, err
-	}
-	agent.mp, err = getClient(ctx, agent.client, agent.server)
-	if err != nil {
-		return ctx, err
-	}
-	return ctx, nil
-}
-
-// install installs the agent, starts it, and configures auto-start on reboot.
-func (agent *Agent) install(ctx context.Context) error {
-	exe, err := os.Executable()
-	if err != nil {
-		return err
-	}
-
-	substitutions := map[string]string{
-		"Agent":          exe,
-		"Server":         agent.server,
-		"ServiceAccount": agent.serviceAccount,
-		"User":           agent.swarmingUser,
-	}
-	content, err := substituteAsset(ctx, agent.agentAutoStartTemplate, substitutions)
-	if err != nil {
-		return err
-	}
-	path, err := substitute(ctx, agent.agentAutoStartPath, substitutions)
-	if err != nil {
-		return err
-	}
-
-	_, err = os.Stat(path)
-	if err == nil || os.IsExist(err) {
-		bytes, err := ioutil.ReadFile(path)
-		if err != nil {
-			return err
-		}
-		if string(bytes) == content {
-			logging.Infof(ctx, "Already installed: %s.", path)
-			return nil
-		}
-		logging.Infof(ctx, "Reinstalling: %s.", path)
-		if err = agent.strategy.stop(ctx); err != nil {
-			return err
-		}
-	} else {
-		logging.Infof(ctx, "Installing: %s.", path)
-	}
-	if err = ioutil.WriteFile(path, []byte(content), 0644); err != nil {
-		return err
-	}
-	return agent.strategy.start(ctx, path)
-}
-
-// poll polls for instructions from Machine Provider.
-//
-// Does not return except in case of error.
-func (agent *Agent) poll(ctx context.Context) error {
-	// Metadata tells us which Machine Provider instance to talk to
-	// and how to authenticate.
-	for {
-		logging.Infof(ctx, "Polling.")
-		instruction, err := agent.mp.poll(ctx, agent.hostname, "GCE")
-		if err != nil {
-			// Log error but don't return. Keep polling.
-			logging.Errorf(ctx, "%s", err.Error())
-		} else {
-			if err = agent.handle(ctx, instruction); err != nil {
-				return err
-			}
-		}
-		tsmon.Flush(ctx)
-		time.Sleep(time.Minute)
-	}
-}
-
-// handle handles a received instruction.
-func (agent *Agent) handle(ctx context.Context, instruction *machine.ComponentsMachineProviderRpcMessagesPollResponse) error {
-	if instruction.State == "" || instruction.State == "EXECUTED" {
-		return nil
-	}
-
-	// The only type of instruction that exists is to connect to Swarming.
-	if instruction.Instruction == nil || instruction.Instruction.SwarmingServer == "" {
-		return nil
-	}
-
-	logging.Infof(ctx, "Received new instruction:\n%s", instruction)
-	start := time.Now()
-	if err := agent.configureSwarmingAutoStart(ctx, instruction.Instruction.SwarmingServer); err != nil {
-		return err
-	}
-	if err := agent.mp.ack(ctx, agent.hostname, "GCE"); err != nil {
-		return err
-	}
-	duration := float64(time.Since(start)) / float64(time.Second)
-	instructionsAcked.Add(ctx, 1, agent.server, instruction.Instruction.SwarmingServer)
-	instructionsAckedTime.Add(ctx, duration, agent.server, instruction.Instruction.SwarmingServer)
-	return agent.reboot(ctx)
-}
-
-// reboot attempts to reboot the machine.
-//
-// Does not return except in case of error.
-func (agent *Agent) reboot(ctx context.Context) error {
-	logging.Infof(ctx, "Rebooting.")
-	tsmon.Flush(ctx)
-	for {
-		if err := agent.strategy.reboot(ctx); err != nil {
-			return err
-		}
-		time.Sleep(60 * time.Second)
-		logging.Infof(ctx, "Waiting to reboot...")
-	}
-}
-
-func Main(args []string) int {
-	var agent *Agent
-	var err error
-
-	var install bool
-	var disk, server, serviceAccount, user string
-	flag.StringVar(&disk, "disk", "", "Disk to use for Swarming.")
-	flag.BoolVar(&install, "install", false, "Install the agent and exit.")
-	flag.StringVar(&server, "server", "", "Machine Provider server URL.")
-	flag.StringVar(&serviceAccount, "gce-service-account", "", "GCE service account name to authenticate with.")
-	flag.StringVar(&user, "user", "chrome-bot", "User to set up Swarming for.")
-	flag.Parse()
-
-	// Set up context and install the command line logger.
-	// Platform-specific agents will set up logging to a file.
-	ctx := context.Background()
-	config := gologger.LoggerConfig{
-		Format: gologger.StdFormatWithColor,
-		Out:    os.Stderr,
-	}
-	ctx = config.Use(ctx)
-
-	// Determine the platform-specific agent to use.
-	agent, err = getAgent(ctx)
-	if err != nil {
-		logging.Errorf(ctx, "%s", err.Error())
-		return 1
-	}
-	agent.server = server
-	agent.serviceAccount = serviceAccount
-	agent.swarmingUser = user
-
-	ctx, err = agent.initialize(ctx)
-	if err != nil {
-		logging.Errorf(ctx, "%s", err.Error())
-		return 1
-	}
-
-	if disk != "" {
-		if err = agent.configureAutoMount(ctx, disk); err != nil {
-			logging.Errorf(ctx, "%s", err.Error())
-			return 1
-		}
-	}
-
-	if install {
-		if err = agent.install(ctx); err != nil {
-			logging.Errorf(ctx, "%s", err.Error())
-			return 1
-		}
-		return 0
-	}
-
-	if err = agent.poll(ctx); err != nil {
-		logging.Errorf(ctx, "%s", err.Error())
-		return 1
-	}
-	return 0
-}
-
-func main() {
-	mathrand.SeedRandomly()
-
-	os.Exit(Main(os.Args[1:]))
-}
diff --git a/mp/cmd/mpagent/metrics.go b/mp/cmd/mpagent/metrics.go
deleted file mode 100644
index f272e37..0000000
--- a/mp/cmd/mpagent/metrics.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"go.chromium.org/luci/common/tsmon/distribution"
-	"go.chromium.org/luci/common/tsmon/field"
-	"go.chromium.org/luci/common/tsmon/metric"
-	"go.chromium.org/luci/common/tsmon/types"
-)
-
-var (
-	instructionsAcked = metric.NewCounter(
-		"machine_provider/agent/instructions/acked",
-		"Number of instructions received from Machine Provider which were acked.",
-		nil,
-		// Machine Provider server the instruction was received from.
-		field.String("mp"),
-		// Swarming server the instruction said to connect to.
-		field.String("swarming"),
-	)
-
-	instructionsAckedTime = metric.NewCumulativeDistribution(
-		"machine_provider/agent/instructions/acked/time",
-		"Number of seconds between instruction receipt and ack.",
-		&types.MetricMetadata{Units: types.Seconds},
-		distribution.DefaultBucketer,
-		// Machine Provider server the instruction was received from.
-		field.String("mp"),
-		// Swarming server the instruction said to connect to.
-		field.String("swarming"),
-	)
-)
diff --git a/mp/cmd/mpagent/swarming-start-bot.bat.tmpl b/mp/cmd/mpagent/swarming-start-bot.bat.tmpl
deleted file mode 100644
index 48a43f0..0000000
--- a/mp/cmd/mpagent/swarming-start-bot.bat.tmpl
+++ /dev/null
@@ -1,7 +0,0 @@
-:: swarming-start-bot - swarming bot startup
-::
-:: Used for starting a Swarming bot process.
-
-:: Prevent Swarming from configuring its own autostart.
-SET SWARMING_EXTERNAL_BOT_SETUP=1
-@C:\tools\python\bin\python.exe {{.Path}} start_bot
diff --git a/mp/cmd/mpagent/swarming-start-bot.conf.tmpl b/mp/cmd/mpagent/swarming-start-bot.conf.tmpl
deleted file mode 100644
index c65ae7b..0000000
--- a/mp/cmd/mpagent/swarming-start-bot.conf.tmpl
+++ /dev/null
@@ -1,13 +0,0 @@
-# swarming-start-bot - swarming bot startup
-#
-# Used for starting a Swarming bot process.
-
-description "swarming bot startup"
-
-start on (filesystem and net-device-up IFACE!=lo)
-stop on shutdown
-limit nofile 50000 50000
-
-script
-  /usr/bin/sudo -H -u {{.User}} SWARMING_EXTERNAL_BOT_SETUP=1 /usr/bin/python {{.Path}} start_bot
-end script
diff --git a/mp/cmd/mpagent/swarming-start-bot.service.tmpl b/mp/cmd/mpagent/swarming-start-bot.service.tmpl
deleted file mode 100644
index 7b00c81..0000000
--- a/mp/cmd/mpagent/swarming-start-bot.service.tmpl
+++ /dev/null
@@ -1,13 +0,0 @@
-[Unit]
-Description=Swarming bot startup
-After=network.target
-
-[Service]
-Type=simple
-User={{.User}}
-LimitNOFILE=50000
-Environment=SWARMING_EXTERNAL_BOT_SETUP=1
-ExecStart=/usr/bin/python {{.Path}} start_bot
-
-[Install]
-WantedBy=multi-user.target
diff --git a/mp/cmd/mpagent/utils.go b/mp/cmd/mpagent/utils.go
deleted file mode 100644
index 6aee6ca..0000000
--- a/mp/cmd/mpagent/utils.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"bytes"
-	"context"
-	"net/http"
-	"text/template"
-
-	machine "go.chromium.org/luci/common/api/machine_provider/machine/v1"
-)
-
-// MachineProvider encapsulates a client for interacting with Machine Provider.
-type MachineProvider struct {
-	client *machine.Service
-}
-
-// getClient returns a new instance of the MachineProvider client.
-func getClient(ctx context.Context, client *http.Client, server string) (*MachineProvider, error) {
-	mp, err := machine.New(client)
-	if err != nil {
-		return nil, err
-	}
-	mp.BasePath = server + "/_ah/api/machine/v1/"
-	return &MachineProvider{client: mp}, nil
-}
-
-// ack acknowledges receipt and execution of a Machine Provider instruction.
-func (mp *MachineProvider) ack(ctx context.Context, hostname, backend string) error {
-	return mp.client.Ack(&machine.ComponentsMachineProviderRpcMessagesAckRequest{
-		Backend:  backend,
-		Hostname: hostname,
-	}).Context(ctx).Do()
-}
-
-// poll polls Machine Provider for instructions.
-//
-// Returns an Instruction.
-func (mp *MachineProvider) poll(ctx context.Context, hostname, backend string) (*machine.ComponentsMachineProviderRpcMessagesPollResponse, error) {
-	return mp.client.Poll(&machine.ComponentsMachineProviderRpcMessagesPollRequest{
-		Backend:  backend,
-		Hostname: hostname,
-	}).Context(ctx).Do()
-}
-
-// substitute reads a template string and performs substitutions.
-//
-// Returns a string.
-func substitute(ctx context.Context, templateString string, substitutions interface{}) (string, error) {
-	template, err := template.New(templateString).Parse(templateString)
-	if err != nil {
-		return "", err
-	}
-	buffer := bytes.Buffer{}
-	if err = template.Execute(&buffer, substitutions); err != nil {
-		return "", nil
-	}
-	return buffer.String(), nil
-}
-
-// substitute asset reads an asset string and performs substitutions.
-//
-// Returns a string.
-func substituteAsset(ctx context.Context, asset string, substitutions interface{}) (string, error) {
-	return substitute(ctx, string(GetAsset(asset)), substitutions)
-}
diff --git a/mp/cmd/mpagent/utils_test.go b/mp/cmd/mpagent/utils_test.go
deleted file mode 100644
index e9ad993..0000000
--- a/mp/cmd/mpagent/utils_test.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2017 The LUCI Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"context"
-	"encoding/json"
-	"io/ioutil"
-	"net/http"
-	"net/http/httptest"
-	"testing"
-
-	. "github.com/smartystreets/goconvey/convey"
-
-	. "go.chromium.org/luci/common/testing/assertions"
-)
-
-func TestAck(t *testing.T) {
-	t.Parallel()
-
-	Convey("ack works", t, func(c C) {
-		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			c.So(r.Header.Get("Content-Type"), ShouldEqual, "application/json")
-			c.So(r.Method, ShouldEqual, "POST")
-
-			j := struct {
-				Backend  string `json:"backend"`
-				Hostname string `json:"hostname"`
-			}{}
-			b, e := ioutil.ReadAll(r.Body)
-			c.So(e, ShouldBeNil)
-			e = json.Unmarshal(b, &j)
-			c.So(e, ShouldBeNil)
-			c.So(j.Backend, ShouldEqual, "backend")
-			c.So(j.Hostname, ShouldEqual, "hostname")
-
-			w.WriteHeader(204)
-		}))
-		defer ts.Close()
-
-		ctx := context.Background()
-		mp, e := getClient(ctx, &http.Client{}, ts.URL)
-		So(e, ShouldBeNil)
-
-		e = mp.ack(ctx, "hostname", "backend")
-		So(e, ShouldBeNil)
-	})
-
-	Convey("Returns 404", t, func(c C) {
-		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			c.So(r.Header.Get("Content-Type"), ShouldEqual, "application/json")
-			c.So(r.Method, ShouldEqual, "POST")
-
-			j := struct {
-				Backend  string `json:"backend"`
-				Hostname string `json:"hostname"`
-			}{}
-			b, e := ioutil.ReadAll(r.Body)
-			c.So(e, ShouldBeNil)
-			e = json.Unmarshal(b, &j)
-			c.So(e, ShouldBeNil)
-			c.So(j.Backend, ShouldEqual, "backend")
-			c.So(j.Hostname, ShouldEqual, "hostname")
-
-			w.WriteHeader(404)
-		}))
-		defer ts.Close()
-
-		ctx := context.Background()
-		mp, e := getClient(ctx, &http.Client{}, ts.URL)
-		So(e, ShouldBeNil)
-
-		e = mp.ack(context.Background(), "hostname", "backend")
-		So(e, ShouldNotBeNil)
-		So(e, ShouldErrLike, "404")
-	})
-}
-
-func TestPoll(t *testing.T) {
-	t.Parallel()
-
-	Convey("poll works", t, func(c C) {
-		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			c.So(r.Header.Get("Content-Type"), ShouldEqual, "application/json")
-			c.So(r.Method, ShouldEqual, "POST")
-
-			j := struct {
-				Backend  string `json:"backend"`
-				Hostname string `json:"hostname"`
-			}{}
-			b, e := ioutil.ReadAll(r.Body)
-			c.So(e, ShouldBeNil)
-			e = json.Unmarshal(b, &j)
-			c.So(e, ShouldBeNil)
-			c.So(j.Backend, ShouldEqual, "backend")
-			c.So(j.Hostname, ShouldEqual, "hostname")
-
-			response := struct {
-				Instruction struct {
-					SwarmingServer string `json:"swarming_server"`
-				} `json:"instruction"`
-				State string `json:"state"`
-			}{}
-
-			w.WriteHeader(200)
-			json.NewEncoder(w).Encode(response)
-		}))
-		defer ts.Close()
-
-		ctx := context.Background()
-		mp, e := getClient(ctx, &http.Client{}, ts.URL)
-		So(e, ShouldBeNil)
-
-		i, e := mp.poll(ctx, "hostname", "backend")
-		So(i.State, ShouldEqual, "")
-		So(e, ShouldBeNil)
-	})
-
-	Convey("Returns 404", t, func(c C) {
-		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			c.So(r.Header.Get("Content-Type"), ShouldEqual, "application/json")
-			c.So(r.Method, ShouldEqual, "POST")
-
-			j := struct {
-				Backend  string `json:"backend"`
-				Hostname string `json:"hostname"`
-			}{}
-			b, e := ioutil.ReadAll(r.Body)
-			c.So(e, ShouldBeNil)
-			e = json.Unmarshal(b, &j)
-			c.So(e, ShouldBeNil)
-			c.So(j.Backend, ShouldEqual, "backend")
-			c.So(j.Hostname, ShouldEqual, "hostname")
-
-			w.WriteHeader(404)
-		}))
-		defer ts.Close()
-
-		ctx := context.Background()
-		mp, e := getClient(ctx, &http.Client{}, ts.URL)
-		So(e, ShouldBeNil)
-
-		i, e := mp.poll(ctx, "hostname", "backend")
-		So(i, ShouldBeNil)
-		So(e, ShouldErrLike, "404")
-	})
-}
-
-func TestSubstitute(t *testing.T) {
-	t.Parallel()
-
-	substitutions := map[string]string{
-		"Field1": "Value 1",
-		"Field2": "Value 2",
-		"Field3": "Value 3",
-	}
-
-	Convey("substitute works", t, func() {
-		s, e := substitute(context.Background(), "Test {{.Field1}} {{.Field2}} {{.Field3}}", substitutions)
-		So(s, ShouldEqual, "Test Value 1 Value 2 Value 3")
-		So(e, ShouldBeNil)
-	})
-
-	Convey("Not all substitutions present in template", t, func() {
-		s, e := substitute(context.Background(), "Test {{.Field2}}", substitutions)
-		So(s, ShouldEqual, "Test Value 2")
-		So(e, ShouldBeNil)
-	})
-
-	Convey("Template parsing error", t, func() {
-		s, e := substitute(context.Background(), "Test {{", substitutions)
-		So(s, ShouldEqual, "")
-		So(e, ShouldNotBeNil)
-	})
-}