diff --git a/assets/golang/site.go b/assets/golang/site.go index 50d2e074d..7bbb8cb4d 100644 --- a/assets/golang/site.go +++ b/assets/golang/site.go @@ -4,56 +4,35 @@ import ( "fmt" "io" "log" - "net" "net/http" "os" "time" ) -type EndpointType struct { - validationName string - path string -} - -var endpointTypeMap = map[string]EndpointType{ - "api.ipify.org": { - validationName: "IPv4", - path: "/ipv4-test", - }, - "api6.ipify.org": { - validationName: "IPv6", - path: "/ipv6-test", - }, - "api64.ipify.org": { - validationName: "Dual stack", - path: "/dual-stack-test", - }, +var endpointMap = map[string]string{ + "/ipv4-test": "https://api.ipify.org", + "/ipv6-test": "https://api6.ipify.org", + "/dual-stack-test": "https://api64.ipify.org", } func main() { - http.HandleFunc("/", handleRequest) + http.HandleFunc("/", hello) http.HandleFunc("/requesturi/", echo) - log.Printf("Starting server on %s\n", os.Getenv("PORT")) - - server := &http.Server{ - Addr: fmt.Sprintf(":%s", os.Getenv("PORT")), + for path, apiURL := range endpointMap { + http.HandleFunc(path, createIPHandler(apiURL)) } - if err := server.ListenAndServe(); err != nil { - log.Fatalf("Could not start server: %s\n", err) + port := os.Getenv("PORT") + if port == "" { + port = "8080" } -} -func handleRequest(res http.ResponseWriter, req *http.Request) { - for endpoint, data := range endpointTypeMap { - if req.URL.Path == data.path { - testEndpoint(res, endpoint, data.validationName) - return - } + fmt.Printf("Listening on port %s...\n", port) + err := http.ListenAndServe(":"+port, nil) + if err != nil { + log.Fatalf("Could not start server: %v\n", err) } - - hello(res, req) } func hello(res http.ResponseWriter, req *http.Request) { @@ -61,18 +40,23 @@ func hello(res http.ResponseWriter, req *http.Request) { } func echo(res http.ResponseWriter, req *http.Request) { - fmt.Fprintln(res, fmt.Sprintf("Request URI is [%s]\nQuery String is [%s]", req.RequestURI, req.URL.RawQuery)) + fmt.Fprintf(res, "Request URI is [%s]\nQuery String is [%s]\n", req.RequestURI, req.URL.RawQuery) } -func testEndpoint(res http.ResponseWriter, endpoint, validationName string) { - client := &http.Client{ - Timeout: 5 * time.Second, +func createIPHandler(apiURL string) http.HandlerFunc { + return func(res http.ResponseWriter, req *http.Request) { + fetchAndWriteIP(res, apiURL) } +} + +func fetchAndWriteIP(res http.ResponseWriter, apiURL string) { + client := &http.Client{Timeout: 5 * time.Second} - resp, err := client.Get(fmt.Sprintf("http://%s", endpoint)) + resp, err := client.Get(apiURL) if err != nil { - log.Printf("Failed to reach %s: %v\n", endpoint, err) - writeTestResponse(res, validationName, false, "Unknown", err.Error()) + log.Printf("Error fetching from %s: %v\n", apiURL, err) + res.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(res, "Error: %v", err) return } defer resp.Body.Close() @@ -80,41 +64,11 @@ func testEndpoint(res http.ResponseWriter, endpoint, validationName string) { body, err := io.ReadAll(resp.Body) if err != nil { log.Printf("Error reading response: %v\n", err) - writeTestResponse(res, validationName, false, "Unknown", err.Error()) + res.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(res, "Error: %v", err) return } - ipType := determineIPType(string(body)) - success := resp.StatusCode == http.StatusOK - - writeTestResponse(res, validationName, success, ipType, "") -} - -func writeTestResponse(res http.ResponseWriter, validationName string, success bool, ipType, errorMsg string) { - responseCode := http.StatusInternalServerError - if success { - responseCode = http.StatusOK - } - res.WriteHeader(responseCode) - - if errorMsg == "" { - errorMsg = "none" - } - - message := fmt.Sprintf("%s validation resulted in %s. Detected IP type is %s. Error message: %s.\n", - validationName, map[bool]string{true: "success", false: "failure"}[success], ipType, errorMsg) - res.Write([]byte(message)) -} - -func determineIPType(ipString string) string { - ip := net.ParseIP(ipString) - if ip == nil { - return "Invalid IP" - } - - if ip.To4() != nil { - return "IPv4" - } - - return "IPv6" + res.WriteHeader(resp.StatusCode) + fmt.Fprintf(res, "%s", string(body)) } \ No newline at end of file diff --git a/assets/java-spring/src/main/java/org/cloudfoundry/SpringBootTrivialApplication.java b/assets/java-spring/src/main/java/org/cloudfoundry/SpringBootTrivialApplication.java index 342eae33f..37121e422 100644 --- a/assets/java-spring/src/main/java/org/cloudfoundry/SpringBootTrivialApplication.java +++ b/assets/java-spring/src/main/java/org/cloudfoundry/SpringBootTrivialApplication.java @@ -7,7 +7,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; @@ -31,9 +30,9 @@ class IPv6TesterController { static { ENDPOINT_TYPE_MAP = new HashMap<>(); - ENDPOINT_TYPE_MAP.put("api.ipify.org", new EndpointInfo("IPv4", "/ipv4-test")); - ENDPOINT_TYPE_MAP.put("api6.ipify.org", new EndpointInfo("IPv6", "/ipv6-test")); - ENDPOINT_TYPE_MAP.put("api64.ipify.org", new EndpointInfo("Dual stack", "/dual-stack-test")); + ENDPOINT_TYPE_MAP.put("api.ipify.org", new EndpointInfo("/ipv4-test")); + ENDPOINT_TYPE_MAP.put("api6.ipify.org", new EndpointInfo("/ipv6-test")); + ENDPOINT_TYPE_MAP.put("api64.ipify.org", new EndpointInfo("/dual-stack-test")); } @GetMapping("/") @@ -64,40 +63,21 @@ private String testEndpoint(String endpoint) { URI uri = new URI("http://" + endpoint + "/"); String response = restTemplate.getForObject(uri, String.class); + if (response == null || response.isEmpty()) { + throw new RuntimeException("Empty response from " + endpoint); + } - String ipType = determineIpType(response); - boolean success = response != null && !response.isEmpty(); - String resultMessage = success ? "success" : "failure"; - - logger.info(endpointInfo.validationName + " validation " + resultMessage); + return response; - return endpointInfo.validationName + " validation resulted in " + resultMessage + - ". Detected IP type is " + ipType + "."; } catch (URISyntaxException e) { logger.severe("URI syntax issue with " + endpoint + ": " + e.getMessage()); - return endpointInfo.validationName + - " validation resulted in failure due to URI issue. Error message: " + e.getMessage() + "."; + return e.getMessage(); } catch (Exception e) { logger.severe("Failed to reach " + endpoint + ": " + e.getMessage()); - return endpointInfo.validationName + - " validation resulted in failure. Error message: " + e.getMessage() + "."; + return e.getMessage(); } } - private String determineIpType(String ipString) { - try { - InetAddress inetAddress = InetAddress.getByName(ipString); - if (inetAddress instanceof java.net.Inet4Address) { - return "IPv4"; - } else if (inetAddress instanceof java.net.Inet6Address) { - return "IPv6"; - } - } catch (Exception e) { - logger.severe("Invalid IP format or unexpected error for: " + ipString + ". Error: " + e.getMessage()); - } - return "Invalid IP"; - } - - private static record EndpointInfo(String validationName, String path) { + private static record EndpointInfo(String path) { } -} \ No newline at end of file +} diff --git a/assets/java-spring/target/spring-boot-trivial-app-0.0.1.jar b/assets/java-spring/target/spring-boot-trivial-app-0.0.1.jar index 258c9c954..671aa19e2 100644 Binary files a/assets/java-spring/target/spring-boot-trivial-app-0.0.1.jar and b/assets/java-spring/target/spring-boot-trivial-app-0.0.1.jar differ diff --git a/assets/nginx-ipv6/nginx.conf b/assets/nginx-ipv6/nginx.conf old mode 100644 new mode 100755 index cac959f07..1de782f5d --- a/assets/nginx-ipv6/nginx.conf +++ b/assets/nginx-ipv6/nginx.conf @@ -11,22 +11,21 @@ http { } location /ipv4-test { - proxy_pass https://api4.ipify.org/?format=json; + proxy_pass https://api4.ipify.org/; proxy_set_header Host api4.ipify.org; proxy_ssl_server_name on; } location /ipv6-test { - proxy_pass https://api6.ipify.org/?format=json; + proxy_pass https://api6.ipify.org/; proxy_set_header Host api6.ipify.org; proxy_ssl_server_name on; } location /dual-stack-test { - proxy_pass https://api64.ipify.org/?format=json; + proxy_pass https://api64.ipify.org/; proxy_set_header Host api64.ipify.org; proxy_ssl_server_name on; } } -} - +} \ No newline at end of file diff --git a/assets/node/server.js b/assets/node/server.js index 5ba41896c..d4c3e4213 100644 --- a/assets/node/server.js +++ b/assets/node/server.js @@ -1,95 +1,37 @@ var http = require('http'); var https = require('https'); -var url = require('url'); -var ip = require('ip'); - -HOST = null; var host = "0.0.0.0"; var port = process.env.PORT || 3000; -const ENDPOINT_TYPE_MAP = { - 'api.ipify.org': { - validation_name: "IPv4", - path: "/ipv4-test" - }, - 'api6.ipify.org': { - validation_name: "IPv6", - path: "/ipv6-test" - }, - 'api64.ipify.org': { - validation_name: "Dual stack", - path: "/dual-stack-test" - } -}; +http.createServer(async function (req, res) { + const path = req.url; + const endpoints = { + '/ipv4-test': 'api.ipify.org', + '/ipv6-test': 'api6.ipify.org', + '/dual-stack-test': 'api64.ipify.org' + }; -function testIPAddress(endpoint, expectedType) { - return new Promise((resolve) => { + const endpoint = endpoints[path]; + + if (endpoint) { https.get(`https://${endpoint}`, (resp) => { let data = ''; - resp.on('data', (chunk) => { data += chunk; }); + resp.on('data', (chunk) => data += chunk); resp.on('end', () => { - let success = false; - let detectedType = 'unknown'; - - if (expectedType === "IPv4" && ip.isV4Format(data)) { - success = true; - detectedType = "IPv4"; - } else if (expectedType === "IPv6" && ip.isV6Format(data)) { - success = true; - detectedType = "IPv6"; - } else if (expectedType === "Dual stack") { - if (ip.isV4Format(data)) { - success = true; - detectedType = "IPv4"; - } else if (ip.isV6Format(data)) { - success = true; - detectedType = "IPv6"; - } - } - - resolve({ - endpoint, - success, - ip_type: detectedType, - error: success ? 'none' : `Expected ${expectedType}, but got ${data}` - }); + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end(data.trim()); }); + }).on("error", (err) => { - resolve({ endpoint, success: false, ip_type: 'unknown', error: err.message }); + console.error(`Error fetching from ${endpoint}: ${err.message}`); + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.end(err.message); }); - }); -} - -http.createServer(async function (req, res) { - const parsedUrl = url.parse(req.url, true); - const path = parsedUrl.pathname; - - let endpoint = null; - for (const [ep, { path: epPath }] of Object.entries(ENDPOINT_TYPE_MAP)) { - if (path === epPath) { - endpoint = ep; - break; - } - } - - if (endpoint) { - const expectedType = ENDPOINT_TYPE_MAP[endpoint].validation_name; - const result = await testIPAddress(endpoint, expectedType); - - const responseCode = result.success ? 200 : 500; - res.writeHead(responseCode, { 'Content-Type': 'text/plain' }); - - const responseMessage = `${expectedType} validation resulted in ${result.success ? 'success' : 'failure'}. Detected IP type is ${result.ip_type}. Error message: ${result.error}.`; - - res.end(responseMessage); - } else { res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.write('

Hello from a node app! '); - res.write('via: ' + host + ':' + port); - res.end('

'); + res.end('Hello from a node app! '); } }).listen(port, host, () => { diff --git a/assets/php/htdocs/.htaccess b/assets/php/htdocs/.htaccess new file mode 100644 index 000000000..923f2e9f2 --- /dev/null +++ b/assets/php/htdocs/.htaccess @@ -0,0 +1,2 @@ +RewriteEngine On +RewriteRule ^(ipv4|ipv6|dual-stack)-test$ ip-test.php?target=$1 [L] \ No newline at end of file diff --git a/assets/php/htdocs/ip-test.php b/assets/php/htdocs/ip-test.php new file mode 100644 index 000000000..e852dd0f0 --- /dev/null +++ b/assets/php/htdocs/ip-test.php @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/assets/python/server.py b/assets/python/server.py index 3c1d1fe1d..4b3ad81c7 100644 --- a/assets/python/server.py +++ b/assets/python/server.py @@ -1,26 +1,9 @@ import os import logging -import ipaddress import http.client - from http.server import HTTPServer, BaseHTTPRequestHandler from socketserver import ThreadingMixIn -ENDPOINT_TYPE_MAP = { - 'api.ipify.org': { - 'validation_name': "IPv4", - 'path': "/ipv4-test" - }, - 'api6.ipify.org': { - 'validation_name': "IPv6", - 'path': "/ipv6-test" - }, - 'api64.ipify.org': { - 'validation_name': "Dual stack", - 'path': "/dual-stack-test" - } -} - DEFAULT_PORT = '8080' HOST = '127.0.0.1' @@ -29,105 +12,42 @@ format='%(asctime)s | %(levelname)s | %(message)s' ) -class IPv6Tester: - """ - The `IPv6Tester` class is responsible for verifying the successful execution of - egress calls using IPv4, IPv6, and Dual Stack configurations, depending on the input. - It offers logging result from the call. - The test execution is deemed successful if the requested endpoint is reached without errors. - - """ - - def __init__(self, endpoints): - self.endpoints = endpoints - - def test_single_address(self, endpoint): - result = self.test_endpoint(endpoint) - self.print_result(endpoint, result) - return result +def fetch_ip(endpoint): + try: + connection = http.client.HTTPConnection(endpoint, timeout=0.20) + connection.request("GET", "/") + response = connection.getresponse() - def print_result(self, endpoint, result): - validation_type = ENDPOINT_TYPE_MAP[endpoint]['validation_name'] - if result['success']: - logging.info(f"{validation_type} validation succeeded.") + if response.status == 200: + ip_data = response.read().strip().decode('utf-8') + connection.close() + return 200, ip_data else: - logging.error(f"{validation_type} validation failed.") - - def test_endpoint(self, endpoint): - try: - logging.info(f"Testing endpoint: {endpoint}") - connection = http.client.HTTPConnection(endpoint, timeout=0.20) - connection.request("GET", "/") - - response = connection.getresponse() - response_data = response.read().strip().decode('utf-8') - ip_type = self.determine_ip_type(response_data) - connection.close() - return { - 'success': response.status == 200, - 'ip_type': ip_type - } - - except Exception as e: - logging.error(f"Failed to reach {endpoint}: {e}") - return { - 'success': False, - 'error': str(e), - 'ip_type': 'Unknown' - } + return 500, f"Error: received status code {response.status}" - @staticmethod - def determine_ip_type(ip_string): - try: - ip = ipaddress.ip_address(ip_string) - return "IPv4" if ip.version == 4 else "IPv6" - except ValueError: - return "Invalid IP" + except Exception as e: + logging.error(f"Failed to fetch IP from {endpoint}: {e}") + return 500, f"Error fetching IP: {e}" class Handler(BaseHTTPRequestHandler): - ''' - The Handler class provides two distinct test paths - for different testing scenarios. The ipv6-path is dedicated - to testing IPv6 egress calls, while the default path is used - for testing the default Hello-Python buildpack test case. - ''' - def do_GET(self): - if self.path in [data['path'] for data in ENDPOINT_TYPE_MAP.values()]: - self.handle_test() - else: - self.send_response(200) - self.end_headers() - message = "Hello python, world!" - self.wfile.write(message.encode('utf-8')) - self.wfile.write('\n'.encode('utf-8')) + endpoints = { + '/ipv4-test': 'api.ipify.org', + '/ipv6-test': 'api6.ipify.org', + '/dual-stack-test': 'api64.ipify.org' + } - def handle_test(self): - endpoint = self.get_endpoint_from_path() + endpoint = endpoints.get(self.path) if endpoint: - tester = IPv6Tester([endpoint]) - result = tester.test_single_address(endpoint) - response_code = 200 if result['success'] else 500 - self.send_response(response_code) + status, message = fetch_ip(endpoint) + self.send_response(status) self.end_headers() - - validation_name = ENDPOINT_TYPE_MAP[endpoint]['validation_name'] - response_message = (f"{validation_name} validation resulted in " - f"{'success' if result['success'] else 'failure'}. Detected IP type is " - f"{result.get('ip_type', 'unknown')}. Error message: {result.get('error', 'none')}.") - self.wfile.write(response_message.encode('utf-8')) - self.wfile.write('\n'.encode('utf-8')) + self.wfile.write(message.encode('utf-8')) else: - self.send_response(404) + self.send_response(200) self.end_headers() - self.wfile.write(b'Endpoint not found\n') - - def get_endpoint_from_path(self): - for endpoint, data in ENDPOINT_TYPE_MAP.items(): - if self.path == data['path']: - return endpoint - return None + self.wfile.write(b'Hello python, world!\n') class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """Handle requests in a separate thread.""" @@ -136,7 +56,7 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): port = int(os.environ.get('PORT', DEFAULT_PORT)) host = os.environ.get('VCAP_APP_HOST', HOST) - print("Going to start server on %s:%s" % (host, port)) + print(f"Going to start server on {host}:{port}") server = ThreadedHTTPServer((host, port), Handler) print('Starting server, use to stop') diff --git a/assets/ruby_simple/main.rb b/assets/ruby_simple/main.rb index 95e1567ef..557096f62 100644 --- a/assets/ruby_simple/main.rb +++ b/assets/ruby_simple/main.rb @@ -1,14 +1,67 @@ require 'sinatra' +require 'net/http' +require 'logger' + STDOUT.sync = true STDERR.sync = true +ENDPOINT_TYPE_MAP = { + :'api.ipify.org' => { + path: '/ipv4-test' + }, + :'api6.ipify.org' => { + path: '/ipv6-test' + }, + :'api64.ipify.org' => { + path: '/dual-stack-test' + } +}.freeze + +def logger + @logger ||= Logger.new($stdout).tap do |log| + log.progname = 'SinatraApp' + log.level = Logger::INFO + end +end + +class IPTester + def initialize(endpoint) + @endpoint = endpoint + end + + def fetch_ip + uri = URI("http://#{@endpoint}/") + + begin + response = Net::HTTP.get_response(uri) + response.body.strip + rescue => e + logger.error("Failed to reach #{@endpoint}: #{e.class} - #{e.message}") + "Error fetching IP: #{e.message}" + end + end +end + +configure do + set :port, ENV.fetch('PORT', 8080).to_i + set :bind, ENV.fetch('VCAP_APP_HOST', '127.0.0.1') +end + +ENDPOINT_TYPE_MAP.each do |endpoint, data| + get data[:path] do + tester = IPTester.new(endpoint) + message = tester.fetch_ip + "#{message}" + end +end + get '/' do <<-RESPONSE -Healthy -It just needed to be restarted! -My application metadata: #{ENV['VCAP_APPLICATION']} -My port: #{ENV['PORT']} -My custom env variable: #{ENV['CUSTOM_VAR']} +Healthy\n +It just needed to be restarted!\n +My application metadata: #{ENV['VCAP_APPLICATION']}\n +My port: #{ENV['PORT']}\n +My custom env variable: #{ENV['CUSTOM_VAR']}\n RESPONSE end @@ -23,4 +76,4 @@ STDOUT.puts "Tick: #{Time.now.to_i}" sleep 1 end -end +end \ No newline at end of file diff --git a/helpers/config/config_test.go b/helpers/config/config_test.go index 129b12057..8bdd8703f 100644 --- a/helpers/config/config_test.go +++ b/helpers/config/config_test.go @@ -204,6 +204,7 @@ type testReporterConfig struct { } const BoshLiteDomain = "bosh-lite.env.wg-ard.ci.cloudfoundry.org" + var tmpFilePath string var testCfg testConfig diff --git a/ipv6/ipv6.go b/ipv6/ipv6.go index c4922df2a..adc7f8593 100644 --- a/ipv6/ipv6.go +++ b/ipv6/ipv6.go @@ -1,7 +1,6 @@ package ipv6 import ( - "encoding/json" "fmt" . "github.com/cloudfoundry/cf-acceptance-tests/cats_suite_helpers" "github.com/cloudfoundry/cf-acceptance-tests/helpers/app_helpers" @@ -14,8 +13,23 @@ import ( . "github.com/onsi/gomega/gexec" "net" "os" + "strings" ) +func ValidateIP(ipAddress, expectedType string) { + parsedIP := net.ParseIP(ipAddress) + Expect(parsedIP).NotTo(BeNil(), "Expected a valid IP address") + + switch expectedType { + case "IPv4": + Expect(parsedIP.To4()).NotTo(BeNil(), "Expected an IPv4 address") + case "IPv6": + Expect(parsedIP.To4()).To(BeNil(), "Expected an IPv6 address") + case "Dual stack": + Expect(parsedIP).NotTo(BeNil(), "Expected either an IPv4 or IPv6 address") + } +} + var _ = IPv6Describe("IPv6 Connectivity Tests", func() { var appName string @@ -29,24 +43,24 @@ var _ = IPv6Describe("IPv6 Connectivity Tests", func() { }) EndpointTypeMap := map[string]struct { - validationName string - path string + expectedType string + path string }{ - "api.ipify.org": { - validationName: "IPv4", - path: "/ipv4-test", + "IPv4": { + expectedType: "IPv4", + path: "/ipv4-test", }, - "api6.ipify.org": { - validationName: "IPv6", - path: "/ipv6-test", + "IPv6": { + expectedType: "IPv6", + path: "/ipv6-test", }, - "api64.ipify.org": { - validationName: "Dual stack", - path: "/dual-stack-test", + "Dual stack": { + expectedType: "Dual stack", + path: "/dual-stack-test", }, - "default": { - validationName: "Default app", - path: "", + "Default": { + expectedType: "", + path: "", }, } @@ -54,13 +68,18 @@ var _ = IPv6Describe("IPv6 Connectivity Tests", func() { pushSession := cf.Cf(commandOptions...) Expect(pushSession.Wait(Config.DetectTimeoutDuration())).To(Exit(0)) - for key, data := range EndpointTypeMap { - response := helpers.CurlApp(Config, appName, data.path) + for _, data := range EndpointTypeMap { + response := helpers.CurlAppWithStatusCode(Config, appName, data.path) - if key == "default" { + if data.expectedType == "" { Expect(response).To(ContainSubstring(defaultPathExpectMessage)) } else { - Expect(response).To(ContainSubstring(fmt.Sprintf("%s validation resulted in success", data.validationName))) + responseParts := strings.Split(response, "\n") + ipAddress := responseParts[0] + statusCode := responseParts[1] + + ValidateIP(ipAddress, data.expectedType) + Expect(statusCode).To(Equal("200")) } } } @@ -76,77 +95,51 @@ var _ = IPv6Describe("IPv6 Connectivity Tests", func() { pushAndValidate(commandOptions, "ok") } - describeIpv6NginxTest := func(assetPath, stack string) { - pushSession := cf.Cf("push", appName, "-s", stack, "-p", assetPath, "-m", DEFAULT_MEMORY_LIMIT) - Expect(pushSession.Wait(Config.DetectTimeoutDuration())).To(Exit(0)) - - isIPv4 := func(ip string) bool { - parsedIP := net.ParseIP(ip) - return parsedIP != nil && parsedIP.To4() != nil - } - - isIPv6 := func(ip string) bool { - parsedIP := net.ParseIP(ip) - return parsedIP != nil && parsedIP.To4() == nil - } - - for key, data := range EndpointTypeMap { - response := helpers.CurlApp(Config, appName, data.path) - - if key == "default" { - Expect(response).To(ContainSubstring("Hello NGINX!")) - } else { - var result map[string]interface{} - Expect(json.Unmarshal([]byte(response), &result)).To(Succeed()) - ip, ok := result["ip"].(string) - Expect(ok).To(BeTrue()) - - validationResult := false - - switch data.validationName { - case "IPv4": - validationResult = isIPv4(ip) - case "IPv6": - validationResult = isIPv6(ip) - case "Dual stack": - validationResult = isIPv4(ip) || isIPv6(ip) - } - - Expect(validationResult).To(BeTrue(), fmt.Sprintf("%s validation failed with the following error: %s", data.validationName, ip)) - } - } + describeIPv6RubyTests := func(assetPath, stack string) { + commandOptions := []string{"push", appName, "-s", stack, "-p", assetPath, "-m", DEFAULT_MEMORY_LIMIT} + pushAndValidate(commandOptions, "Healthy") } Describe("Egress Capability in Apps", func() { for _, stack := range Config.GetStacks() { - Context(fmt.Sprintf("Using Python stack: %s", stack), func() { It("validates IPv6 egress for Python App", func() { describeIPv6Tests(assets.NewAssets().Python, stack) }) }) - - Context(fmt.Sprintf("Using Node.js stack: %s", stack), func() { - It("validates IPv6 egress for Node.js App", func() { + Context(fmt.Sprintf("Using Node stack: %s", stack), func() { + It("validates IPv6 egress for Node App", func() { describeIPv6Tests(assets.NewAssets().Node, stack) }) }) + Context(fmt.Sprintf("Using Go stack: %s", stack), func() { + It("validates IPv6 egress for Go App", func() { + describeIPv6Tests(assets.NewAssets().Golang, stack) + }) + }) + Context(fmt.Sprintf("Using JavaSpring stack: %s", stack), func() { It("validates IPv6 egress for JavaSpring App", func() { describeIPv6JavaSpringTest(stack) }) }) - Context(fmt.Sprintf("Using Golang stack: %s", stack), func() { - It("validates IPv6 egress for Golang App", func() { - describeIPv6Tests(assets.NewAssets().Golang, stack) + Context(fmt.Sprintf("Using Ruby stack: %s", stack), func() { + It("validates IPv6 egress for Ruby App", func() { + describeIPv6RubyTests(assets.NewAssets().RubySimple, stack) }) }) Context(fmt.Sprintf("Using Nginx stack: %s", stack), func() { It("validates IPv6 egress for Nginx App", func() { - describeIpv6NginxTest(assets.NewAssets().NginxIPv6, stack) + describeIPv6Tests(assets.NewAssets().NginxIPv6, stack) + }) + }) + + Context(fmt.Sprintf("Using PHP stack: %s", stack), func() { + It("validates IPv6 egress for PHP App", func() { + describeIPv6Tests(assets.NewAssets().Php, stack) }) }) } diff --git a/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/app_commands.go b/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/app_commands.go index e8c4bd825..60268c952 100644 --- a/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/app_commands.go +++ b/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/app_commands.go @@ -27,6 +27,12 @@ func CurlApp(cfg helpersinternal.CurlConfig, appName, path string, args ...strin return appCurler.CurlAndWait(cfg, appName, path, CURL_TIMEOUT, args...) } +// Curls an app's endpoint and exit successfully before the default timeout +func CurlAppWithStatusCode(cfg helpersinternal.CurlConfig, appName, path string, args ...string) string { + appCurler := helpersinternal.NewAppCurler(Curl, cfg) + return appCurler.CurlWithStatusCode(cfg, appName, path, CURL_TIMEOUT, args...) +} + // Curls an app's root endpoint and exit successfully before the default timeout func CurlAppRoot(cfg helpersinternal.CurlConfig, appName string) string { appCurler := helpersinternal.NewAppCurler(Curl, cfg) diff --git a/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/internal/app_curler.go b/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/internal/app_curler.go index 7623d3469..2a103ee62 100644 --- a/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/internal/app_curler.go +++ b/vendor/github.com/cloudfoundry/cf-test-helpers/v2/helpers/internal/app_curler.go @@ -34,3 +34,15 @@ func (appCurler *AppCurler) CurlAndWait(cfg CurlConfig, appName string, path str ExpectWithOffset(3, string(curlCmd.Err.Contents())).To(HaveLen(0)) return string(curlCmd.Out.Contents()) } + + +func (appCurler *AppCurler) CurlWithStatusCode(cfg CurlConfig, appName string, path string, timeout time.Duration, args ...string) string { + appUri := appCurler.UriCreator.AppUri(appName, path) + curlArgs := append([]string{"-s", "-w", "\n%{http_code}", appUri}, args...) + + curlCmd := appCurler.CurlFunc(cfg, curlArgs...).Wait(timeout) + + ExpectWithOffset(3, curlCmd).To(gexec.Exit(0)) + ExpectWithOffset(3, string(curlCmd.Err.Contents())).To(HaveLen(0)) + return string(curlCmd.Out.Contents()) +}