-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#155198696] Signed-off-by: Kalai Wei <[email protected]>
- Loading branch information
1 parent
4d86b63
commit fbba00f
Showing
13 changed files
with
505 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package acceptance | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"net/http/httptest" | ||
"net/http/httputil" | ||
"os/exec" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/onsi/gomega/gexec" | ||
) | ||
|
||
var _ = Describe("create VM extension", func() { | ||
var server *httptest.Server | ||
BeforeEach(func() { | ||
server = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
|
||
switch req.URL.Path { | ||
case "/uaa/oauth/token": | ||
w.Write([]byte(`{ | ||
"access_token": "some-opsman-token", | ||
"token_type": "bearer", | ||
"expires_in": 3600 | ||
}`)) | ||
case "/api/v0/staged/vm_extensions": | ||
Expect(req.Method).To(Equal(http.MethodPost)) | ||
|
||
body, err := ioutil.ReadAll(req.Body) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
Expect(body).To(MatchJSON(` | ||
{ | ||
"name": "some-vm-extension", | ||
"cloud_properties": { | ||
"iam_instance_profile": "some-iam-profile", | ||
"elbs": ["some-elb"] | ||
} | ||
} | ||
`)) | ||
|
||
responseJSON, err := json.Marshal([]byte("{}")) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
w.Write([]byte(responseJSON)) | ||
default: | ||
out, err := httputil.DumpRequest(req, true) | ||
Expect(err).NotTo(HaveOccurred()) | ||
Fail(fmt.Sprintf("unexpected request: %s", out)) | ||
} | ||
})) | ||
}) | ||
|
||
It("creates a VM extension in OpsMan", func() { | ||
command := exec.Command(pathToMain, | ||
"--target", server.URL, | ||
"--username", "some-username", | ||
"--password", "some-password", | ||
"--skip-ssl-validation", | ||
"create-vm-extension", | ||
"--name", "some-vm-extension", | ||
"--cloud-properties", "{ \"iam_instance_profile\": \"some-iam-profile\", \"elbs\": [\"some-elb\"] }", | ||
) | ||
|
||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
Eventually(session).Should(gexec.Exit(0)) | ||
Expect(string(session.Out.Contents())).To(Equal("VM Extension 'some-vm-extension' created\n")) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package api | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
type VMExtensionsService struct { | ||
client httpClient | ||
} | ||
|
||
type CreateVMExtension struct { | ||
Name string `json:"name"` | ||
CloudProperties json.RawMessage `json:"cloud_properties"` | ||
} | ||
|
||
func NewVMExtensionsService(client httpClient) VMExtensionsService { | ||
return VMExtensionsService{ | ||
client: client, | ||
} | ||
} | ||
|
||
type VMExtensionInput struct { | ||
Name string `json:"name"` | ||
CloudProperties string `json:"cloud_properties"` | ||
} | ||
|
||
func (v VMExtensionsService) Create(input CreateVMExtension) error { | ||
jsonData, err := json.Marshal(&input) | ||
|
||
if err != nil { | ||
return fmt.Errorf("could not marshal json: %s", err) | ||
} | ||
|
||
verb := "POST" | ||
endpoint := "/api/v0/staged/vm_extensions" | ||
req, err := http.NewRequest(verb, endpoint, bytes.NewReader(jsonData)) | ||
if err != nil { | ||
return fmt.Errorf("could not create api request %s %s: %s", verb, endpoint, err.Error()) | ||
} | ||
req.Header.Add("Content-Type", "application/json") | ||
|
||
resp, err := v.client.Do(req) | ||
if err != nil { | ||
return fmt.Errorf("could not send api request to %s %s: %s", verb, endpoint, err.Error()) | ||
} | ||
|
||
if err = ValidateStatusOK(resp); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package api_test | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"io/ioutil" | ||
"net/http" | ||
"strings" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/pivotal-cf/om/api" | ||
"github.com/pivotal-cf/om/api/fakes" | ||
) | ||
|
||
var _ = Describe("VMExtensionsService", func() { | ||
var ( | ||
client *fakes.HttpClient | ||
vmExtensionsService api.VMExtensionsService | ||
) | ||
|
||
BeforeEach(func() { | ||
client = &fakes.HttpClient{} | ||
vmExtensionsService = api.NewVMExtensionsService(client) | ||
|
||
client.DoReturns(&http.Response{ | ||
StatusCode: http.StatusOK, | ||
Body: ioutil.NopCloser(strings.NewReader(`{}`))}, nil) | ||
}) | ||
|
||
It("creates a VM Extension", func() { | ||
err := vmExtensionsService.Create(api.CreateVMExtension{ | ||
Name: "some-vm-extension", | ||
CloudProperties: json.RawMessage(`{ "iam_instance_profile": "some-iam-profile", "elbs": ["some-elb"] }`), | ||
}) | ||
|
||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
Expect(client.DoCallCount()).To(Equal(1)) | ||
req := client.DoArgsForCall(0) | ||
|
||
Expect(req.Method).To(Equal("POST")) | ||
Expect(req.URL.Path).To(Equal("/api/v0/staged/vm_extensions")) | ||
Expect(req.Header.Get("Content-Type")).To(Equal("application/json")) | ||
|
||
jsonBody, err := ioutil.ReadAll(req.Body) | ||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(jsonBody).To(MatchJSON(`{ | ||
"name": "some-vm-extension", | ||
"cloud_properties": {"iam_instance_profile": "some-iam-profile", "elbs": ["some-elb"]} | ||
}`)) | ||
}) | ||
|
||
Context("failure cases", func() { | ||
It("returns an error when the http status is non-200", func() { | ||
|
||
client.DoReturns(&http.Response{ | ||
StatusCode: http.StatusInternalServerError, | ||
Body: ioutil.NopCloser(strings.NewReader(`{}`))}, nil) | ||
|
||
err := vmExtensionsService.Create(api.CreateVMExtension{ | ||
Name: "some-vm-extension", | ||
CloudProperties: json.RawMessage(`{ "iam_instance_profile": "some-iam-profile", "elbs": ["some-elb"] }`), | ||
}) | ||
|
||
Expect(err).To(MatchError(ContainSubstring("500 Internal Server Error"))) | ||
}) | ||
|
||
It("returns an error when the api endpoint fails", func() { | ||
client.DoReturns(&http.Response{ | ||
StatusCode: http.StatusOK, | ||
Body: ioutil.NopCloser(strings.NewReader(`{}`))}, errors.New("api endpoint failed")) | ||
|
||
err := vmExtensionsService.Create(api.CreateVMExtension{ | ||
Name: "some-vm-extension", | ||
CloudProperties: json.RawMessage(`{ "iam_instance_profile": "some-iam-profile", "elbs": ["some-elb"] }`), | ||
}) | ||
|
||
Expect(err).To(MatchError("could not send api request to POST /api/v0/staged/vm_extensions: api endpoint failed")) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package commands | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/pivotal-cf/jhanda" | ||
"github.com/pivotal-cf/om/api" | ||
) | ||
|
||
//go:generate counterfeiter -o ./fakes/vm_extension_creator.go --fake-name VMExtensionCreator . vmExtensionCreator | ||
type vmExtensionCreator interface { | ||
Create(api.CreateVMExtension) error | ||
} | ||
|
||
type CreateVMExtension struct { | ||
service vmExtensionCreator | ||
logger logger | ||
Options struct { | ||
Name string `long:"name" short:"n" required:"true" description:"VM extension name"` | ||
CloudProperties string `long:"cloud-properties" short:"cp" required:"true" description:"cloud properties in JSON format"` | ||
} | ||
} | ||
|
||
func NewCreateVMExtension(service vmExtensionCreator, logger logger) CreateVMExtension { | ||
return CreateVMExtension{ | ||
service: service, | ||
logger: logger, | ||
} | ||
} | ||
|
||
func (c CreateVMExtension) Execute(args []string) error { | ||
if _, err := jhanda.Parse(&c.Options, args); err != nil { | ||
return fmt.Errorf("could not parse create-vm-extension flags: %s", err) | ||
} | ||
|
||
err := c.service.Create(api.CreateVMExtension{ | ||
Name: c.Options.Name, | ||
CloudProperties: json.RawMessage(c.Options.CloudProperties), | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
c.logger.Printf("VM Extension '%s' created\n", c.Options.Name) | ||
|
||
return nil | ||
} | ||
|
||
func (c CreateVMExtension) Usage() jhanda.Usage { | ||
return jhanda.Usage{ | ||
Description: "This creates a VM extension", | ||
ShortDescription: "creates a VM extension", | ||
Flags: c.Options, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package commands_test | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/pivotal-cf/jhanda" | ||
"github.com/pivotal-cf/om/api" | ||
"github.com/pivotal-cf/om/commands" | ||
"github.com/pivotal-cf/om/commands/fakes" | ||
) | ||
|
||
var _ = Describe("CreateVMExtension", func() { | ||
var ( | ||
fakeVMExtensionService *fakes.VMExtensionCreator | ||
fakeLogger *fakes.Logger | ||
command commands.CreateVMExtension | ||
) | ||
|
||
BeforeEach(func() { | ||
fakeVMExtensionService = &fakes.VMExtensionCreator{} | ||
fakeLogger = &fakes.Logger{} | ||
command = commands.NewCreateVMExtension(fakeVMExtensionService, fakeLogger) | ||
}) | ||
|
||
Describe("Execute", func() { | ||
It("makes a request to the OpsMan to create a VM extension", func() { | ||
err := command.Execute([]string{ | ||
"--name", "some-vm-extension", | ||
"--cloud-properties", "{ \"iam_instance_profile\": \"some-iam-profile\", \"elbs\": [\"some-elb\"] }", | ||
}) | ||
|
||
Expect(err).NotTo(HaveOccurred()) | ||
Expect(fakeVMExtensionService.CreateArgsForCall(0)).To(Equal(api.CreateVMExtension{ | ||
Name: "some-vm-extension", | ||
CloudProperties: json.RawMessage(`{ "iam_instance_profile": "some-iam-profile", "elbs": ["some-elb"] }`), | ||
})) | ||
|
||
Expect(fakeLogger.PrintfCallCount()).To(Equal(1)) | ||
format, content := fakeLogger.PrintfArgsForCall(0) | ||
Expect(fmt.Sprintf(format, content...)).To(Equal("VM Extension 'some-vm-extension' created\n")) | ||
}) | ||
|
||
Context("failure cases", func() { | ||
Context("when the service fails to create a VM extension", func() { | ||
It("returns an error", func() { | ||
fakeVMExtensionService.CreateReturns(errors.New("failed to create VM extension")) | ||
|
||
err := command.Execute([]string{ | ||
"--name", "some-vm-extension", | ||
"--cloud-properties", "{ \"iam_instance_profile\": \"some-iam-profile\", \"elbs\": [\"some-elb\"] }", | ||
}) | ||
|
||
Expect(err).To(MatchError("failed to create VM extension")) | ||
}) | ||
}) | ||
|
||
Context("when an unknown flag is provided", func() { | ||
It("returns an error", func() { | ||
err := command.Execute([]string{"--badflag"}) | ||
Expect(err).To(MatchError("could not parse create-vm-extension flags: flag provided but not defined: -badflag")) | ||
}) | ||
}) | ||
}) | ||
}) | ||
|
||
Describe("Usage", func() { | ||
It("returns usage information for the command", func() { | ||
command := commands.NewCreateVMExtension(nil, nil) | ||
Expect(command.Usage()).To(Equal(jhanda.Usage{ | ||
Description: "This creates a VM extension", | ||
ShortDescription: "creates a VM extension", | ||
Flags: command.Options, | ||
})) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.