mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	Merge pull request #111618 from Jiawei0227/flocker
cleanup: Remove flocker volume plugins from k8s codebase
This commit is contained in:
		
							
								
								
									
										190
									
								
								vendor/github.com/clusterhq/flocker-go/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										190
									
								
								vendor/github.com/clusterhq/flocker-go/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,190 +0,0 @@
 | 
			
		||||
                                Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   Copyright 2014-2016 ClusterHQ
 | 
			
		||||
 | 
			
		||||
   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.
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/github.com/clusterhq/flocker-go/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/clusterhq/flocker-go/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,18 +0,0 @@
 | 
			
		||||
flocker-go
 | 
			
		||||
==========
 | 
			
		||||
 | 
			
		||||
[](https://circleci.com/gh/ClusterHQ/flocker-go)
 | 
			
		||||
 | 
			
		||||
flocker-go implements the package `flocker` that will let you easily interact
 | 
			
		||||
with a Flocker Control Service.
 | 
			
		||||
 | 
			
		||||
What can it do?
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
You can check the package documentation here: https://godoc.org/github.com/ClusterHQ/flocker-go
 | 
			
		||||
 | 
			
		||||
TODO
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
- Define a proper interface `flockerClientable` with all the needed methods for
 | 
			
		||||
  wrapping the Flocker API.
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/github.com/clusterhq/flocker-go/circle.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/clusterhq/flocker-go/circle.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,16 +0,0 @@
 | 
			
		||||
machine:
 | 
			
		||||
  timezone:
 | 
			
		||||
    America/Los_Angeles
 | 
			
		||||
 | 
			
		||||
# Output the test output to circle.
 | 
			
		||||
test:
 | 
			
		||||
  pre: 
 | 
			
		||||
    - go get -u github.com/jstemmer/go-junit-report
 | 
			
		||||
  override:
 | 
			
		||||
    - go test -coverprofile=coverage.out -v -race ./... > test.out
 | 
			
		||||
    - cat test.out | go-junit-report > report.xml
 | 
			
		||||
    - go tool cover -func=coverage.out
 | 
			
		||||
  post:
 | 
			
		||||
    - mv test.out $CIRCLE_ARTIFACTS/
 | 
			
		||||
    - mv report.xml $CIRCLE_TEST_REPORTS/
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										376
									
								
								vendor/github.com/clusterhq/flocker-go/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										376
									
								
								vendor/github.com/clusterhq/flocker-go/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,376 +0,0 @@
 | 
			
		||||
package flocker
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// From https://github.com/ClusterHQ/flocker-docker-plugin/blob/master/flockerdockerplugin/adapter.py#L18
 | 
			
		||||
const defaultVolumeSize = json.Number("107374182400")
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// A volume can take a long time to be available, if we don't want
 | 
			
		||||
	// Kubernetes to wait forever we need to stop trying after some time, that
 | 
			
		||||
	// time is defined here
 | 
			
		||||
	timeoutWaitingForVolume = 2 * time.Minute
 | 
			
		||||
	tickerWaitingForVolume  = 5 * time.Second
 | 
			
		||||
 | 
			
		||||
	errStateNotFound         = errors.New("State not found by Dataset ID")
 | 
			
		||||
	errConfigurationNotFound = errors.New("Configuration not found by Name")
 | 
			
		||||
 | 
			
		||||
	errFlockerControlServiceHost = errors.New("The volume config must have a key CONTROL_SERVICE_HOST defined in the OtherAttributes field")
 | 
			
		||||
	errFlockerControlServicePort = errors.New("The volume config must have a key CONTROL_SERVICE_PORT defined in the OtherAttributes field")
 | 
			
		||||
 | 
			
		||||
	errVolumeAlreadyExists = errors.New("The volume already exists")
 | 
			
		||||
	errVolumeDoesNotExist  = errors.New("The volume does not exist")
 | 
			
		||||
 | 
			
		||||
	errUpdatingDataset = errors.New("It was impossible to update the dataset")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Clientable exposes the needed methods to implement your own Flocker Client.
 | 
			
		||||
type Clientable interface {
 | 
			
		||||
	CreateDataset(options *CreateDatasetOptions) (*DatasetState, error)
 | 
			
		||||
	DeleteDataset(datasetID string) error
 | 
			
		||||
 | 
			
		||||
	GetDatasetState(datasetID string) (*DatasetState, error)
 | 
			
		||||
	GetDatasetID(metaName string) (datasetID string, err error)
 | 
			
		||||
	GetPrimaryUUID() (primaryUUID string, err error)
 | 
			
		||||
 | 
			
		||||
	ListNodes() (nodes []NodeState, err error)
 | 
			
		||||
 | 
			
		||||
	UpdatePrimaryForDataset(primaryUUID, datasetID string) (*DatasetState, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client is a default Flocker Client.
 | 
			
		||||
type Client struct {
 | 
			
		||||
	*http.Client
 | 
			
		||||
 | 
			
		||||
	schema  string
 | 
			
		||||
	host    string
 | 
			
		||||
	port    int
 | 
			
		||||
	version string
 | 
			
		||||
 | 
			
		||||
	clientIP string
 | 
			
		||||
 | 
			
		||||
	maximumSize json.Number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Clientable = &Client{}
 | 
			
		||||
 | 
			
		||||
// NewClient creates a wrapper over http.Client to communicate with the flocker control service.
 | 
			
		||||
func NewClient(host string, port int, clientIP string, caCertPath, keyPath, certPath string) (*Client, error) {
 | 
			
		||||
	client, err := newTLSClient(caCertPath, keyPath, certPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Client{
 | 
			
		||||
		Client:      client,
 | 
			
		||||
		schema:      "https",
 | 
			
		||||
		host:        host,
 | 
			
		||||
		port:        port,
 | 
			
		||||
		version:     "v1",
 | 
			
		||||
		maximumSize: defaultVolumeSize,
 | 
			
		||||
		clientIP:    clientIP,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
request do a request using the http.Client embedded to the control service
 | 
			
		||||
and returns the response or an error in case it happens.
 | 
			
		||||
 | 
			
		||||
Note: you will need to deal with the response body call to Close if you
 | 
			
		||||
don't want to deal with problems later.
 | 
			
		||||
*/
 | 
			
		||||
func (c Client) request(method, url string, payload interface{}) (*http.Response, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		b   []byte
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if method == "POST" { // Just allow payload on POST
 | 
			
		||||
		b, err = json.Marshal(payload)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req, err := http.NewRequest(method, url, bytes.NewBuffer(b))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	req.Header.Set("Content-Type", "application/json")
 | 
			
		||||
 | 
			
		||||
	// REMEMBER TO CLOSE THE BODY IN THE OUTSIDE FUNCTION
 | 
			
		||||
	return c.Do(req)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// post performs a post request with the indicated payload
 | 
			
		||||
func (c Client) post(url string, payload interface{}) (*http.Response, error) {
 | 
			
		||||
	return c.request("POST", url, payload)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// delete performs a delete request with the indicated payload
 | 
			
		||||
func (c Client) delete(url string, payload interface{}) (*http.Response, error) {
 | 
			
		||||
	return c.request("DELETE", url, payload)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get performs a get request
 | 
			
		||||
func (c Client) get(url string) (*http.Response, error) {
 | 
			
		||||
	return c.request("GET", url, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getURL returns a full URI to the control service
 | 
			
		||||
func (c Client) getURL(path string) string {
 | 
			
		||||
	return fmt.Sprintf("%s://%s:%d/%s/%s", c.schema, c.host, c.port, c.version, path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type configurationPayload struct {
 | 
			
		||||
	Deleted     bool            `json:"deleted"`
 | 
			
		||||
	Primary     string          `json:"primary"`
 | 
			
		||||
	DatasetID   string          `json:"dataset_id,omitempty"`
 | 
			
		||||
	MaximumSize json.Number     `json:"maximum_size,omitempty"`
 | 
			
		||||
	Metadata    metadataPayload `json:"metadata,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CreateDatasetOptions struct {
 | 
			
		||||
	Primary     string            `json:"primary"`
 | 
			
		||||
	DatasetID   string            `json:"dataset_id,omitempty"`
 | 
			
		||||
	MaximumSize int64             `json:"maximum_size,omitempty"`
 | 
			
		||||
	Metadata    map[string]string `json:"metadata,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type metadataPayload struct {
 | 
			
		||||
	Name string `json:"name,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DatasetState struct {
 | 
			
		||||
	Path        string      `json:"path"`
 | 
			
		||||
	DatasetID   string      `json:"dataset_id"`
 | 
			
		||||
	Primary     string      `json:"primary,omitempty"`
 | 
			
		||||
	MaximumSize json.Number `json:"maximum_size,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type datasetStatePayload struct {
 | 
			
		||||
	*DatasetState
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NodeState struct {
 | 
			
		||||
	UUID string `json:"uuid"`
 | 
			
		||||
	Host string `json:"host"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// findIDInConfigurationsPayload returns the datasetID if it was found in the
 | 
			
		||||
// configurations payload, otherwise it will return an error.
 | 
			
		||||
func (c Client) findIDInConfigurationsPayload(body io.ReadCloser, name string) (datasetID string, err error) {
 | 
			
		||||
	var configurations []configurationPayload
 | 
			
		||||
	if err = json.NewDecoder(body).Decode(&configurations); err == nil {
 | 
			
		||||
		for _, r := range configurations {
 | 
			
		||||
			if r.Metadata.Name == name {
 | 
			
		||||
				return r.DatasetID, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return "", errConfigurationNotFound
 | 
			
		||||
	}
 | 
			
		||||
	return "", err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListNodes returns a list of dataset agent nodes from Flocker Control Service
 | 
			
		||||
func (c *Client) ListNodes() (nodes []NodeState, err error) {
 | 
			
		||||
	resp, err := c.get(c.getURL("state/nodes"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []NodeState{}, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
	if resp.StatusCode >= 300 {
 | 
			
		||||
		return []NodeState{}, fmt.Errorf("Expected: {1,2}xx listing nodes, got: %d", resp.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = json.NewDecoder(resp.Body).Decode(&nodes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []NodeState{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return nodes, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPrimaryUUID returns the UUID of the primary Flocker Control Service for
 | 
			
		||||
// the given host.
 | 
			
		||||
func (c Client) GetPrimaryUUID() (uuid string, err error) {
 | 
			
		||||
	states, err := c.ListNodes()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, s := range states {
 | 
			
		||||
		if s.Host == c.clientIP {
 | 
			
		||||
			return s.UUID, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return "", fmt.Errorf("No node found with IP '%s', available nodes %+v", c.clientIP, states)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteDataset performs a delete request to the given datasetID
 | 
			
		||||
func (c *Client) DeleteDataset(datasetID string) error {
 | 
			
		||||
	url := c.getURL(fmt.Sprintf("configuration/datasets/%s", datasetID))
 | 
			
		||||
	resp, err := c.delete(url, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode >= 300 {
 | 
			
		||||
		return fmt.Errorf("Expected: {1,2}xx deleting the dataset %s, got: %d", datasetID, resp.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDatasetState performs a get request to get the state of the given datasetID, if
 | 
			
		||||
// something goes wrong or the datasetID was not found it returns an error.
 | 
			
		||||
func (c Client) GetDatasetState(datasetID string) (*DatasetState, error) {
 | 
			
		||||
	resp, err := c.get(c.getURL("state/datasets"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	var states []datasetStatePayload
 | 
			
		||||
	if err = json.NewDecoder(resp.Body).Decode(&states); err == nil {
 | 
			
		||||
		for _, s := range states {
 | 
			
		||||
			if s.DatasetID == datasetID {
 | 
			
		||||
				return s.DatasetState, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errStateNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
CreateDataset creates a volume in Flocker, waits for it to be ready and
 | 
			
		||||
returns the dataset id.
 | 
			
		||||
 | 
			
		||||
This process is a little bit complex but follows this flow:
 | 
			
		||||
 | 
			
		||||
1. Find the Flocker Control Service UUID
 | 
			
		||||
2. If it already exists an error is returned
 | 
			
		||||
3. If it didn't previously exist, wait for it to be ready
 | 
			
		||||
*/
 | 
			
		||||
func (c *Client) CreateDataset(options *CreateDatasetOptions) (datasetState *DatasetState, err error) {
 | 
			
		||||
	// 1) Find the primary Flocker UUID
 | 
			
		||||
	// Note: it could be cached, but doing this query we health check it
 | 
			
		||||
	if options.Primary == "" {
 | 
			
		||||
		options.Primary, err = c.GetPrimaryUUID()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if options.MaximumSize == 0 {
 | 
			
		||||
		options.MaximumSize, _ = c.maximumSize.Int64()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := c.post(c.getURL("configuration/datasets"), options)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	// 2) Return if the dataset was previously created
 | 
			
		||||
	if resp.StatusCode == http.StatusConflict {
 | 
			
		||||
		return nil, errVolumeAlreadyExists
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode >= 300 {
 | 
			
		||||
		return nil, fmt.Errorf("Expected: {1,2}xx creating the volume, got: %d", resp.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var p configurationPayload
 | 
			
		||||
	if err := json.NewDecoder(resp.Body).Decode(&p); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 3) Wait until the dataset is ready for usage. In case it never gets
 | 
			
		||||
	// ready there is a timeoutChan that will return an error
 | 
			
		||||
	timeoutChan := time.NewTimer(timeoutWaitingForVolume).C
 | 
			
		||||
	tickChan := time.NewTicker(tickerWaitingForVolume).C
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		var strErrDel string
 | 
			
		||||
		s, err := c.GetDatasetState(p.DatasetID)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return s, nil
 | 
			
		||||
		} else if err != errStateNotFound {
 | 
			
		||||
			errDel := c.DeleteDataset(p.DatasetID)
 | 
			
		||||
			if errDel != nil {
 | 
			
		||||
				strErrDel = fmt.Sprintf(", deletion of dataset failed with %s", errDel)
 | 
			
		||||
			}
 | 
			
		||||
			return nil, fmt.Errorf("Flocker API error during dataset creation (datasetID %s): %s%s", p.DatasetID, err, strErrDel)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		select {
 | 
			
		||||
		case <-timeoutChan:
 | 
			
		||||
			errDel := c.DeleteDataset(p.DatasetID)
 | 
			
		||||
			if errDel != nil {
 | 
			
		||||
				strErrDel = fmt.Sprintf(", deletion of dataset failed with %s", errDel)
 | 
			
		||||
			}
 | 
			
		||||
			return nil, fmt.Errorf("Flocker API timeout during dataset creation (datasetID %s): %s%s", p.DatasetID, err, strErrDel)
 | 
			
		||||
		case <-tickChan:
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdatePrimaryForDataset will update the Primary for the given dataset
 | 
			
		||||
// returning the current DatasetState.
 | 
			
		||||
func (c Client) UpdatePrimaryForDataset(newPrimaryUUID, datasetID string) (*DatasetState, error) {
 | 
			
		||||
	payload := struct {
 | 
			
		||||
		Primary string `json:"primary"`
 | 
			
		||||
	}{
 | 
			
		||||
		Primary: newPrimaryUUID,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	url := c.getURL(fmt.Sprintf("configuration/datasets/%s", datasetID))
 | 
			
		||||
	resp, err := c.post(url, payload)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode >= 300 {
 | 
			
		||||
		return nil, errUpdatingDataset
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var s DatasetState
 | 
			
		||||
	if err := json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &s, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDatasetID will return the DatasetID found for the given metadata name.
 | 
			
		||||
func (c Client) GetDatasetID(metaName string) (datasetID string, err error) {
 | 
			
		||||
	resp, err := c.get(c.getURL("configuration/datasets"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	var configurations []configurationPayload
 | 
			
		||||
	if err = json.NewDecoder(resp.Body).Decode(&configurations); err == nil {
 | 
			
		||||
		for _, c := range configurations {
 | 
			
		||||
			if c.Metadata.Name == metaName && c.Deleted == false {
 | 
			
		||||
				return c.DatasetID, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return "", errConfigurationNotFound
 | 
			
		||||
	}
 | 
			
		||||
	return "", err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/clusterhq/flocker-go/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/clusterhq/flocker-go/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,2 +0,0 @@
 | 
			
		||||
// flocker package allows you to easily interact with a Flocker Control Service.
 | 
			
		||||
package flocker
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/clusterhq/flocker-go/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/clusterhq/flocker-go/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,34 +0,0 @@
 | 
			
		||||
package flocker
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"crypto/x509"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// newTLSClient returns a new TLS http client
 | 
			
		||||
func newTLSClient(caCertPath, keyPath, certPath string) (*http.Client, error) {
 | 
			
		||||
	// Client certificate
 | 
			
		||||
	cert, err := tls.LoadX509KeyPair(certPath, keyPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// CA certificate
 | 
			
		||||
	caCert, err := ioutil.ReadFile(caCertPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	caCertPool := x509.NewCertPool()
 | 
			
		||||
	caCertPool.AppendCertsFromPEM(caCert)
 | 
			
		||||
 | 
			
		||||
	tlsConfig := &tls.Config{
 | 
			
		||||
		Certificates: []tls.Certificate{cert},
 | 
			
		||||
		RootCAs:      caCertPool,
 | 
			
		||||
	}
 | 
			
		||||
	tlsConfig.BuildNameToCertificate()
 | 
			
		||||
	transport := &http.Transport{TLSClientConfig: tlsConfig}
 | 
			
		||||
 | 
			
		||||
	return &http.Client{Transport: transport}, nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user