Skip to content

Commit

Permalink
Expand test coverage, reinforce mocks (taiidani#16)
Browse files Browse the repository at this point in the history
* Expand test coverage, reinforce mocks

* A little more coverage around config
  • Loading branch information
taiidani committed Aug 16, 2020
1 parent 81fdf20 commit b8c500f
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 27 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ jobs:
JENKINS_URL: "http://localhost:8080"
JENKINS_USERNAME: "admin"
JENKINS_PASSWORD: "admin"
run: go test -v -cover ./...
run: go test -v -covermode=atomic -coverprofile=coverage.txt ./...

- name: Send coverage to Codecov
run: bash <(curl -s https://codecov.io/bash) -Z -f coverage.txt -F acceptance
2 changes: 1 addition & 1 deletion .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ jobs:
run: go test -race -covermode=atomic -coverprofile=coverage.txt ./...

- name: Send coverage to Codecov
run: bash <(curl -s https://codecov.io/bash) -Z -f coverage.txt
run: bash <(curl -s https://codecov.io/bash) -Z -f coverage.txt -F unit
10 changes: 7 additions & 3 deletions example/job.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
resource jenkins_folder example {
name = "folder-name"
description = "A sample folder"
template = <<EOT
name = "folder-name"
description = "A sample folder"
template = <<EOT
<com.cloudbees.hudson.plugins.folder.Folder plugin="cloudbees-folder@6.6">
<actions/>
<description>{{ .Description }}</description>
Expand All @@ -16,6 +16,10 @@ resource jenkins_folder example {
<icon class="com.cloudbees.hudson.plugins.folder.icons.StockFolderIcon"/>
</com.cloudbees.hudson.plugins.folder.Folder>
EOT

lifecycle {
ignore_changes = [template]
}
}

resource jenkins_job pipeline {
Expand Down
2 changes: 1 addition & 1 deletion example/providers.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Connects to the instance launched through "docker-compose up -d"
# Once done with testing, clean up the instance with "docker-compose down"
# Once done with testing, clean up the instance with "docker-compose down --volumes"
provider jenkins {
server_url = "http://localhost:8080" # Or use JENKINS_URL env var
username = "admin" # Or use JENKINS_USERNAME env var
Expand Down
28 changes: 19 additions & 9 deletions jenkins/config.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,45 @@
package jenkins

import (
"io"
"io/ioutil"

jenkins "github.com/bndr/gojenkins"
)

type jenkinsClient interface {
CreateJobInFolder(config string, jobName string, parentIDs ...string) (*jenkins.Job, error)
Credentials() *jenkins.CredentialsManager
DeleteJob(name string) (bool, error)
GetJob(id string, parentIDs ...string) (*jenkins.Job, error)
}

// jenkinsAdapter wraps the Jenkins client, enabling additional functionality
type jenkinsAdapter struct {
*jenkins.Jenkins
}

// Config is the set of parameters needed to configure the Jenkins provider.
type Config struct {
ServerURL string
CACert string
CACert io.Reader
Username string
Password string
}

func newJenkinsClient(c *Config) (*jenkins.Jenkins, error) {
func newJenkinsClient(c *Config) *jenkinsAdapter {
client := jenkins.CreateJenkins(nil, c.ServerURL, c.Username, c.Password)
if c.CACert != "" {
if c.CACert != nil {
// provide CA certificate if server is using self-signed certificate
client.Requester.CACert, _ = ioutil.ReadFile(c.CACert)
}
_, err := client.Init()
if err != nil {
return nil, err
client.Requester.CACert, _ = ioutil.ReadAll(c.CACert)
}

// return the Jenkins API client
return client, nil
return &jenkinsAdapter{Jenkins: client}
}

func (j *jenkinsAdapter) Credentials() *jenkins.CredentialsManager {
return &jenkins.CredentialsManager{
J: j.Jenkins,
}
}
45 changes: 42 additions & 3 deletions jenkins/config_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
package jenkins

import jenkins "github.com/bndr/gojenkins"
import (
"bytes"
"testing"

jenkins "github.com/bndr/gojenkins"
)

type mockJenkinsClient struct {
mockDeleteJob func(name string) (bool, error)
mockGetJob func(id string, parentIDs ...string) (*jenkins.Job, error)
mockCreateJobInFolder func(config string, jobName string, parentIDs ...string) (*jenkins.Job, error)
mockDeleteJob func(name string) (bool, error)
mockGetJob func(id string, parentIDs ...string) (*jenkins.Job, error)
}

func (m *mockJenkinsClient) CreateJobInFolder(config string, jobName string, parentIDs ...string) (*jenkins.Job, error) {
return m.mockCreateJobInFolder(config, jobName, parentIDs...)
}

func (m *mockJenkinsClient) Credentials() *jenkins.CredentialsManager {
return &jenkins.CredentialsManager{}
}

func (m *mockJenkinsClient) DeleteJob(name string) (bool, error) {
Expand All @@ -14,3 +28,28 @@ func (m *mockJenkinsClient) DeleteJob(name string) (bool, error) {
func (m *mockJenkinsClient) GetJob(id string, parentIDs ...string) (*jenkins.Job, error) {
return m.mockGetJob(id, parentIDs...)
}

func TestNewJenkinsClient(t *testing.T) {
c := newJenkinsClient(&Config{})
if c == nil {
t.Errorf("Expected populated client")
}

c = newJenkinsClient(&Config{
CACert: bytes.NewBufferString("certificate"),
})
if string(c.Requester.CACert) != "certificate" {
t.Errorf("Initialization did not extract certificate data")
}
}

func TestJenkinsAdapter_Credentials(t *testing.T) {
c := newJenkinsClient(&Config{})
cm := c.Credentials()

if cm == nil {
t.Errorf("Expected populated client")
} else if cm.J != c.Jenkins {
t.Error("Expected credentials client to match client")
}
}
15 changes: 12 additions & 3 deletions jenkins/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package jenkins

import (
"context"
"os"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -49,13 +50,21 @@ func Provider() *schema.Provider {
func configureProvider(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
config := Config{
ServerURL: d.Get("server_url").(string),
CACert: d.Get("ca_cert").(string),
Username: d.Get("username").(string),
Password: d.Get("password").(string),
}

client, err := newJenkinsClient(&config)
if err != nil {
// Read the certificate
var err error
if d.Get("ca_cert").(string) != "" {
config.CACert, err = os.Open(d.Get("ca_cert").(string))
if err != nil {
return nil, diag.Errorf("Unable to open certificate file %s: %s", d.Get("ca_cert").(string), err.Error())
}
}

client := newJenkinsClient(&config)
if _, err = client.Init(); err != nil {
return nil, diag.FromErr(err)
}

Expand Down
3 changes: 1 addition & 2 deletions jenkins/resource_jenkins_folder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"testing"

jenkins "github.com/bndr/gojenkins"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
Expand All @@ -26,7 +25,7 @@ func TestAccJenkinsFolder_basic(t *testing.T) {
}

func testAccCheckJenkinsFolderDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*jenkins.Jenkins)
client := testAccProvider.Meta().(jenkinsClient)

for _, rs := range s.RootModule().Resources {
if rs.Type != "jenkins_folder" {
Expand Down
5 changes: 2 additions & 3 deletions jenkins/resource_jenkins_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"log"
"strings"

jenkins "github.com/bndr/gojenkins"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
Expand Down Expand Up @@ -41,7 +40,7 @@ func resourceJenkinsJob() *schema.Resource {
}

func resourceJenkinsJobCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*jenkins.Jenkins)
client := meta.(jenkinsClient)
name := formatJobName(d.Get("name").(string))
baseName, folders := parseJobName(d.Get("name").(string))

Expand Down Expand Up @@ -92,7 +91,7 @@ func resourceJenkinsJobRead(ctx context.Context, d *schema.ResourceData, meta in
}

func resourceJenkinsJobUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*jenkins.Jenkins)
client := meta.(jenkinsClient)
name := d.Id()

// grab job by current name
Expand Down
2 changes: 1 addition & 1 deletion jenkins/resource_jenkins_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestAccJenkinsJob_basic(t *testing.T) {
}

func testAccCheckJenkinsJobDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*jenkins.Jenkins)
client := testAccProvider.Meta().(jenkinsClient)

for _, rs := range s.RootModule().Resources {
if rs.Type != "jenkins_job" {
Expand Down

0 comments on commit b8c500f

Please sign in to comment.