Skip to content

Commit

Permalink
Config: Add option for ingress http/https port
Browse files Browse the repository at this point in the history
This patch try to solve user issue where port 80 or 443 already in
use and `crc start` fails by providing user an option as part of `crc
config set` to have different http/https port.

This patch also add callback function and startup warning in case port
setting is choose by user.
```
$ crc config set ingress-http-port 8080
Changes to configuration property 'ingress-http-port' will break the openshift route.
User need to add 8080 port to application route to access it. like http://myapp.apps-crc.testing:8080

$ crc start
[...]
Use the 'oc' command line interface:
  $ eval $(crc oc-env)
  $ oc login -u developer https://api.crc.testing:6443

Warning: Port 80 is already in use. Assigned port 8080 instead.
You have to add thise port to the application route to access
it. like http://myapp.apps-crc.testing:8080

$ curl --unix-socket ~/.crc/crc-http.sock http:/unix/network/services/forwarder/all | jq .
[
  {
    "local": "127.0.0.1:2222",
    "remote": "192.168.127.2:22",
    "protocol": "tcp"
  },
  {
    "local": "127.0.0.1:6443",
    "remote": "192.168.127.2:6443",
    "protocol": "tcp"
  },
  {
    "local": ":443",
    "remote": "192.168.127.2:443",
    "protocol": "tcp"
  },
  {
    "local": ":8080",
    "remote": "192.168.127.2:80",
    "protocol": "tcp"
  }
]
```
  • Loading branch information
praveenkumar committed Sep 16, 2022
1 parent 9afa0b9 commit 04ce01c
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 14 deletions.
39 changes: 35 additions & 4 deletions cmd/crc/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"runtime"
"strings"
"text/template"

"github.com/Masterminds/semver/v3"
Expand Down Expand Up @@ -75,6 +76,8 @@ func runStart(ctx context.Context) (*types.StartResult, error) {
KubeAdminPassword: config.Get(crcConfig.KubeAdminPassword).AsString(),
Preset: crcConfig.GetPreset(config),
EnableSharedDirs: crcConfig.ShouldEnableSharedDirs(config),
IngressHTTPPort: config.Get(crcConfig.IngressHTTPPort).AsUInt(),
IngressHTTPSPort: config.Get(crcConfig.IngressHTTPSPort).AsUInt(),
}

client := newMachine()
Expand Down Expand Up @@ -249,10 +252,11 @@ If you find an issue, please report it at https://github.com/openshift/okd
)

type templateVariables struct {
ClusterConfig *clusterConfig
EvalCommandLine string
CommandLinePrefix string
PodmanRemote string
ClusterConfig *clusterConfig
EvalCommandLine string
CommandLinePrefix string
PodmanRemote string
FallbackPortWarning string
}

func writeTemplatedMessage(writer io.Writer, s *startResult) error {
Expand All @@ -268,6 +272,10 @@ func writeOpenShiftTemplatedMessage(writer io.Writer, s *startResult) error {
if s.ClusterConfig.ClusterType == preset.OKD {
tmpl = fmt.Sprintf("%s\n\n%s", startTemplateForOpenshift, startTemplateForOKD)
}
fallbackPortWarning := portFallbackWarning()
if fallbackPortWarning != "" {
tmpl = fmt.Sprintf("%s\n%s", tmpl, fallbackPortWarning)
}
parsed, err := template.New("template").Parse(tmpl)
if err != nil {
return err
Expand Down Expand Up @@ -321,3 +329,26 @@ func checkDaemonStarted() error {
}
return daemonclient.CheckIfOlderVersion(v)
}

func portFallbackWarning() string {
var fallbackPortWarning string
httpScheme := "http"
httpsScheme := "https"
fallbackPortWarningTmpl := `
Warning: Port %d is used for OpenShift %s routes instead of the default
You have to add this port to %s URLs when accessing OpenShift application,
such as %s://myapp.apps-crc.testing:%d
`
ingressHTTPPort := config.Get(crcConfig.IngressHTTPPort).AsUInt()
ingressHTTPSPort := config.Get(crcConfig.IngressHTTPSPort).AsUInt()

if ingressHTTPSPort != constants.OpenShiftIngressHTTPSPort {
fallbackPortWarning += fmt.Sprintf(fallbackPortWarningTmpl,
ingressHTTPSPort, strings.ToUpper(httpsScheme), strings.ToUpper(httpsScheme), httpsScheme, ingressHTTPSPort)
}
if ingressHTTPPort != constants.OpenShiftIngressHTTPPort {
fallbackPortWarning += fmt.Sprintf(fallbackPortWarningTmpl,
ingressHTTPPort, strings.ToUpper(httpScheme), strings.ToUpper(httpScheme), httpScheme, ingressHTTPPort)
}
return fallbackPortWarning
}
2 changes: 2 additions & 0 deletions pkg/crc/api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ func getStartConfig(cfg crcConfig.Storage, args client.StartConfig) types.StartC
NameServer: cfg.Get(crcConfig.NameServer).AsString(),
PullSecret: cluster.NewNonInteractivePullSecretLoader(cfg, args.PullSecretFile),
KubeAdminPassword: cfg.Get(crcConfig.KubeAdminPassword).AsString(),
IngressHTTPPort: cfg.Get(crcConfig.IngressHTTPPort).AsUInt(),
IngressHTTPSPort: cfg.Get(crcConfig.IngressHTTPSPort).AsUInt(),
Preset: crcConfig.GetPreset(cfg),
EnableSharedDirs: crcConfig.ShouldEnableSharedDirs(cfg),
}
Expand Down
13 changes: 13 additions & 0 deletions pkg/crc/config/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,16 @@ func RequiresCRCSetup(key string, _ interface{}) string {
return fmt.Sprintf("Changes to configuration property '%s' are only applied during 'crc setup'.\n"+
"Please run 'crc setup' for this configuration to take effect.", key)
}

func RequiresHTTPPortChangeWarning(key string, value interface{}) string {
return fmt.Sprintf("Changes to configuration property '%s' will break OpenShift HTTP routes.\n"+
"In order to access OpenShift applications through HTTP URLs "+
"the %d port must be manually specified, such as http://myapp.apps-crc.testing:%d", key, value, value)
}

func RequiresHTTPSPortChangeWarning(key string, value interface{}) string {
return fmt.Sprintf("Changes to configuration property '%s' will break OpenShift HTTPS routes.\n"+
"In order to access OpenShift applications through HTTPS URLs "+
"the %d port must be manually specified, such as https://myapp.apps-crc.testing:%d\n"+
"After this change, the OpenShift console will be non-functional because of OpenShift limitations", key, value, value)
}
6 changes: 6 additions & 0 deletions pkg/crc/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const (
KubeAdminPassword = "kubeadmin-password"
Preset = "preset"
EnableSharedDirs = "enable-shared-dirs"
IngressHTTPPort = "ingress-http-port"
IngressHTTPSPort = "ingress-https-port"
)

func RegisterSettings(cfg *Config) {
Expand Down Expand Up @@ -107,6 +109,10 @@ func RegisterSettings(cfg *Config) {

cfg.AddSetting(KubeAdminPassword, "", ValidateString, SuccessfullyApplied,
"User defined kubeadmin password")
cfg.AddSetting(IngressHTTPPort, constants.OpenShiftIngressHTTPPort, ValidatePort, RequiresHTTPPortChangeWarning,
fmt.Sprintf("HTTP port to use for OpenShift ingress/routes on the host (1024-65535, default: %d)", constants.OpenShiftIngressHTTPPort))
cfg.AddSetting(IngressHTTPSPort, constants.OpenShiftIngressHTTPSPort, ValidatePort, RequiresHTTPSPortChangeWarning,
fmt.Sprintf("HTTPS port to use for OpenShift ingress/routes on the host (1024-65535, default: %d)", constants.OpenShiftIngressHTTPSPort))
}

func defaultCPUs(cfg Storage) int {
Expand Down
4 changes: 4 additions & 0 deletions pkg/crc/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func (v SettingValue) AsInt() int {
return cast.ToInt(v.Value)
}

func (v SettingValue) AsUInt() uint {
return cast.ToUint(v.Value)
}

// validationFnType takes the key, value as args and checks if valid
type ValidationFnType func(interface{}) (bool, string)
type SetFn func(string, interface{}) string
Expand Down
11 changes: 11 additions & 0 deletions pkg/crc/config/validations.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,14 @@ func validatePreset(value interface{}) (bool, string) {
}
return true, ""
}

func ValidatePort(value interface{}) (bool, string) {
port, err := cast.ToUintE(value)
if err != nil {
return false, "Requires integer value in range of 1024-65535"
}
if port < 1024 || port > 65535 {
return false, fmt.Sprintf("Provided %d but requires value in range of 1024-65535", port)
}
return true, ""
}
3 changes: 3 additions & 0 deletions pkg/crc/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const (
ClusterDomain = ".crc.testing"
AppsDomain = ".apps-crc.testing"

OpenShiftIngressHTTPPort = 80
OpenShiftIngressHTTPSPort = 443

// This public key is owned by the CRC team (crc@crc.dev), and is used
// to sign bundles uploaded to an image registry.
// It can be fetched with: `gpg --recv-key DC7EAC400A1BFDFB`
Expand Down
2 changes: 1 addition & 1 deletion pkg/crc/machine/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func (client *client) Start(ctx context.Context, startConfig types.StartConfig)
}

if client.useVSock() {
if err := exposePorts(startConfig.Preset); err != nil {
if err := exposePorts(startConfig.Preset, startConfig.IngressHTTPPort, startConfig.IngressHTTPSPort); err != nil {
return nil, err
}
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/crc/machine/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ type StartConfig struct {

// Shared dirs
EnableSharedDirs bool

// Ports to access openshift routes
IngressHTTPPort uint
IngressHTTPSPort uint
}

type ClusterConfig struct {
Expand Down
18 changes: 9 additions & 9 deletions pkg/crc/machine/vsock.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"github.com/pkg/errors"
)

func exposePorts(preset crcPreset.Preset) error {
portsToExpose := vsockPorts(preset)
func exposePorts(preset crcPreset.Preset, ingressHTTPPort, ingressHTTPSPort uint) error {
portsToExpose := vsockPorts(preset, ingressHTTPPort, ingressHTTPSPort)
daemonClient := daemonclient.New()
alreadyOpenedPorts, err := listOpenPorts(daemonClient)
if err != nil {
Expand Down Expand Up @@ -78,13 +78,13 @@ const (
virtualMachineIP = "192.168.127.2"
internalSSHPort = "22"
localIP = "127.0.0.1"
httpPort = "80"
httpsPort = "443"
remoteHTTPPort = "80"
remoteHTTPSPort = "443"
apiPort = "6443"
cockpitPort = "9090"
)

func vsockPorts(preset crcPreset.Preset) []types.ExposeRequest {
func vsockPorts(preset crcPreset.Preset, ingressHTTPPort, ingressHTTPSPort uint) []types.ExposeRequest {
exposeRequest := []types.ExposeRequest{
{
Protocol: "tcp",
Expand All @@ -102,13 +102,13 @@ func vsockPorts(preset crcPreset.Preset) []types.ExposeRequest {
},
types.ExposeRequest{
Protocol: "tcp",
Local: fmt.Sprintf(":%s", httpsPort),
Remote: net.JoinHostPort(virtualMachineIP, httpsPort),
Local: fmt.Sprintf(":%d", ingressHTTPSPort),
Remote: net.JoinHostPort(virtualMachineIP, remoteHTTPSPort),
},
types.ExposeRequest{
Protocol: "tcp",
Local: fmt.Sprintf(":%s", httpPort),
Remote: net.JoinHostPort(virtualMachineIP, httpPort),
Local: fmt.Sprintf(":%d", ingressHTTPPort),
Remote: net.JoinHostPort(virtualMachineIP, remoteHTTPPort),
})
case crcPreset.Podman:
socketProtocol := types.UNIX
Expand Down

0 comments on commit 04ce01c

Please sign in to comment.