Skip to content

Commit

Permalink
Merge pull request #1384 from cloudfoundry/fbsb-docker-app
Browse files Browse the repository at this point in the history
Docker test for file-based service bindings
  • Loading branch information
jochenehret authored Dec 18, 2024
2 parents 99633fa + 8ec1584 commit 1ed09b9
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 2 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/build-catnip-docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Create and publish a Docker image with the "catnip" app

on:
push:
branches: ['develop']
paths:
- 'assets/catnip/**'

env:
REGISTRY: ghcr.io
IMAGE_NAME: cloudfoundry/catnip-app

jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: ./assets/catnip/
file: ./assets/catnip/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ include_app_syslog_tcp
* `include_app_syslog_tcp`: Flag to include the app syslog drain over TCP test group.
* `include_apps`: Flag to include the apps test group.
* `readiness_health_checks_enabled`: Defaults to `true`. Set to false if you are using an environment without readiness health checks.
* `include_cnb`: Flag to include tests related to building apps using Cloud Native Buildpacks. Diego must be deployed and the CC API diego_cnb feature flag must be enabled for these tests to pass.
* `include_cnb`: Flag to include tests related to building apps using Cloud Native Buildpacks. Diego must be deployed and the CC API diego_cnb feature flag must be enabled for these tests to pass. The CF CLI version must be at least v8.9.0.
* `include_container_networking`: Flag to include tests related to container networking.
* `credhub_mode`: Valid values are `assisted` or `non-assisted`. [See below](#credhub-modes).
* `credhub_location`: Location of CredHub instance; default is `https://credhub.service.cf.internal:8844`
Expand Down Expand Up @@ -359,7 +359,7 @@ Test Group Name| Description
`cnb` | Tests our ability to use cloud native buildpacks.
`detect` | Tests the ability of the platform to detect the correct buildpack for compiling an application if no buildpack is explicitly specified.
`docker`| Tests our ability to run docker containers on Diego and that we handle docker metadata correctly.
`file-based service bindings`| Tests file-based service bindings for a buildpack and a CNB app.
`file-based service bindings`| Tests file-based service bindings for a buildpack app, a CNB app and a Docker app.
`internet_dependent`| Tests the feature of being able to specify a buildpack via a Github URL. As such, this depends on your Cloud Foundry application containers having access to the Internet. You should take into account the configuration of the network into which you've deployed your Cloud Foundry, as well as any security group settings applied to application containers.
`isolation_segments` | This test group requires that Diego be deployed with a minimum of 2 cells. One of those cells must have been deployed with a `placement_tag`. If the deployment has been deployed with a routing isolation segment, `isolation_segment_domain` must also be set. For more information, please refer to the [Isolation Segments documentation](https://docs.cloudfoundry.org/adminguide/isolation-segments.html).
`route_services` | Tests the [Route Services](https://docs.cloudfoundry.org/services/route-services.html) feature of Cloud Foundry.
Expand Down
8 changes: 8 additions & 0 deletions assets/catnip/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM golang
WORKDIR /go/src/app
COPY ./ ./

RUN go build -o /go/bin/catnip /go/src/app/main.go

ENV PORT=8080
CMD ["/go/bin/catnip"]
4 changes: 4 additions & 0 deletions cats_suite_helpers/cats_suite_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func CNBDescribe(description string, callback func()) bool {
const (
BuildpackLifecycle string = "buildpack"
CNBLifecycle = "CNB"
DockerLifecycle = "Docker"
)

func FileBasedServiceBindingsDescribe(description string, lifecycle string, callback func()) bool {
Expand All @@ -123,6 +124,9 @@ func FileBasedServiceBindingsDescribe(description string, lifecycle string, call
if lifecycle == CNBLifecycle && (!Config.GetIncludeFileBasedServiceBindings() || !Config.GetIncludeCNB()) {
Skip(skip_messages.SkipFileBasedServiceBindingsCnbApp)
}
if lifecycle == DockerLifecycle && (!Config.GetIncludeFileBasedServiceBindings() || !Config.GetIncludeDocker()) {
Skip(skip_messages.SkipFileBasedServiceBindingsDockerApp)
}
})
Describe(description, callback)
})
Expand Down
16 changes: 16 additions & 0 deletions file_based_service_bindings/file_based_service_bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ var _ = FileBasedServiceBindingsDescribe("Enabling file based service binding fo
callback(CNBLifecycle)
})

var _ = FileBasedServiceBindingsDescribe("Enabling file based service binding for a Docker app", DockerLifecycle, func() {
callback(DockerLifecycle)
})

var callback = func(lifecycle string) {
var appName, serviceName string

Expand Down Expand Up @@ -77,6 +81,9 @@ var callback = func(lifecycle string) {
if lifecycle == CNBLifecycle {
Expect(cf.Cf("create-app", appName, "--app-type", "cnb", "--buildpack", Config.GetGoBuildpackName()).Wait()).To(Exit(0))
}
if lifecycle == DockerLifecycle {
Expect(cf.Cf("create-app", appName, "--app-type", "docker").Wait()).To(Exit(0))
}
appGuid := app_helpers.GetAppGuid(appName)

appFeatureUrl := fmt.Sprintf("/v3/apps/%s/features/file-based-service-bindings", appGuid)
Expand All @@ -101,6 +108,15 @@ var callback = func(lifecycle string) {
).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
}

if lifecycle == DockerLifecycle {
Expect(cf.Cf(
"push",
appName,
"--docker-image", Config.GetCatnipDockerAppImage(),
"-m", DEFAULT_MEMORY_LIMIT,
).Wait(Config.CfPushTimeoutDuration())).To(Exit(0))
}

checkFileContent("binding-guid", getServiceBindingGuid(appGuid, serviceGuid))
checkFileContent("instance-guid", serviceGuid)
checkFileContent("instance-name", serviceName)
Expand Down
1 change: 1 addition & 0 deletions helpers/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type CatsConfig interface {
SleepTimeoutDuration() time.Duration

GetPublicDockerAppImage() string
GetCatnipDockerAppImage() string
}

func NewCatsConfig(path string) (CatsConfig, error) {
Expand Down
21 changes: 21 additions & 0 deletions helpers/config/config_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ type config struct {
PrivateDockerRegistryUsername *string `json:"private_docker_registry_username"`
PrivateDockerRegistryPassword *string `json:"private_docker_registry_password"`
PublicDockerAppImage *string `json:"public_docker_app_image"`
CatnipDockerAppImage *string `json:"catnip_docker_app_image"`

UnallocatedIPForSecurityGroup *string `json:"unallocated_ip_for_security_group"`

Expand Down Expand Up @@ -240,6 +241,7 @@ func getDefaults() config {
defaults.PrivateDockerRegistryUsername = ptrToString("")
defaults.PrivateDockerRegistryPassword = ptrToString("")
defaults.PublicDockerAppImage = ptrToString("cloudfoundry/diego-docker-app:latest")
defaults.CatnipDockerAppImage = ptrToString("ghcr.io/cloudfoundry/catnip-app:latest")

defaults.UnallocatedIPForSecurityGroup = ptrToString("10.0.244.255")

Expand Down Expand Up @@ -292,6 +294,11 @@ func validateConfig(config *config) error {

}

err = validateCatnipDockerAppImage(config)
if err != nil {
errs = errors.Join(errs, err)
}

err = validatePrivateDockerRegistry(config)
if err != nil {
errs = errors.Join(errs, err)
Expand Down Expand Up @@ -602,6 +609,16 @@ func validatePublicDockerAppImage(config *config) error {
return nil
}

func validateCatnipDockerAppImage(config *config) error {
if config.CatnipDockerAppImage == nil {
return fmt.Errorf("* 'catnip_docker_app_image' must not be null")
}
if config.GetCatnipDockerAppImage() == "" {
return fmt.Errorf("* Invalid configuration: 'catnip_docker_app_image' must be set to a valid image source")
}
return nil
}

func validatePrivateDockerRegistry(config *config) error {
if config.IncludePrivateDockerRegistry == nil {
return fmt.Errorf("* 'include_private_docker_registry' must not be null")
Expand Down Expand Up @@ -1123,6 +1140,10 @@ func (c *config) GetPublicDockerAppImage() string {
return *c.PublicDockerAppImage
}

func (c *config) GetCatnipDockerAppImage() string {
return *c.CatnipDockerAppImage
}

func (c *config) GetUnallocatedIPForSecurityGroup() string {
return *c.UnallocatedIPForSecurityGroup
}
Expand Down
27 changes: 27 additions & 0 deletions helpers/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type testConfig struct {
PrivateDockerRegistryUsername *string `json:"private_docker_registry_username,omitempty"`
PrivateDockerRegistryPassword *string `json:"private_docker_registry_password,omitempty"`
PublicDockerAppImage *string `json:"public_docker_app_image,omitempty"`
CatnipDockerAppImage *string `json:"catnip_docker_app_image,omitempty"`

IsolationSegmentName *string `json:"isolation_segment_name,omitempty"`
IsolationSegmentDomain *string `json:"isolation_segment_domain,omitempty"`
Expand Down Expand Up @@ -633,6 +634,32 @@ var _ = Describe("Config", func() {
})
})

Context("when including catnip_docker_app_image", func() {
Context("when image name is set", func() {
var image = "some-image"
BeforeEach(func() {
testCfg.CatnipDockerAppImage = ptrToString(image)
})

It("has the value in the config", func() {
config, err := cfg.NewCatsConfig(tmpFilePath)
Expect(err).NotTo(HaveOccurred())
Expect(config.GetCatnipDockerAppImage()).To(Equal(image))
})
})

Context("when image is an empty string", func() {
BeforeEach(func() {
testCfg.CatnipDockerAppImage = ptrToString("")
})

It("returns an error", func() {
_, err := cfg.NewCatsConfig(tmpFilePath)
Expect(err).To(MatchError("* Invalid configuration: 'catnip_docker_app_image' must be set to a valid image source"))
})
})
})

Context("when including isolation segment tests", func() {
BeforeEach(func() {
testCfg.IncludeIsolationSegments = ptrToBool(true)
Expand Down
1 change: 1 addition & 0 deletions helpers/skip_messages/skip_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const SkipCNBMessage = `Skipping this test because config.IncludeCNB is set to '
NOTE: Ensure CNB lifecycle is enabled on your platform before enabling this test.`
const SkipFileBasedServiceBindingsBuildpackApp = `Skipping this test because config.IncludeFileBasedServiceBindings is set to 'false'.`
const SkipFileBasedServiceBindingsCnbApp = `Skipping this test because config.IncludeFileBasedServiceBindings and/or config.IncludeCNB are set to 'false'.`
const SkipFileBasedServiceBindingsDockerApp = `Skipping this test because config.IncludeFileBasedServiceBindings and/or config.IncludeDocker are set to 'false'.`
const SkipInternetDependentMessage = `Skipping this test because config.IncludeInternetDependent is set to 'false'.
NOTE: Ensure that your platform has access to the internet before running this test.`
const SkipPrivateDockerRegistryMessage = `Skipping this test because config.IncludePrivateDockerRegistry is set to 'false'.
Expand Down

0 comments on commit 1ed09b9

Please sign in to comment.