Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image builder proxy and redhat satellite changes for RedHat Subscription Management #2488

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions projects/aws/image-builder/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
)

var (
eksaVersion string
eksaVersion string
eksaReleaseManifest string
codebuild = os.Getenv(codebuildCIEnvVar)
codebuild = os.Getenv(codebuildCIEnvVar)
)

func (b *BuildOptions) BuildImage() {
Expand All @@ -29,7 +29,7 @@ func (b *BuildOptions) BuildImage() {
// Clean up build tooling repo in cwd
cleanup(buildToolingRepoPath)
}

gitCommitFromBundle, detectedEksaVersion, err := b.getGitCommitFromBundle()
if err != nil {
log.Fatalf("Error getting git commit from bundle: %v", err)
Expand Down Expand Up @@ -62,7 +62,7 @@ func (b *BuildOptions) BuildImage() {
var outputArtifactPath string
var outputImageGlob []string
commandEnvVars := []string{
fmt.Sprintf("%s=%s", releaseBranchEnvVar, b.ReleaseChannel),
fmt.Sprintf("%s=%s", releaseBranchEnvVar, b.ReleaseChannel),
fmt.Sprintf("%s=%s", eksAReleaseVersionEnvVar, detectedEksaVersion),
fmt.Sprintf("%s=%s", eksAReleaseManifestURLEnvVar, getEksAReleasesManifestURL()),
}
Expand Down Expand Up @@ -111,6 +111,13 @@ func (b *BuildOptions) BuildImage() {
commandEnvVars = append(commandEnvVars, fmt.Sprintf("%s=%s", packerAdditionalFilesConfigFileEnvVar, additionalFilesConfigFile))
}
if b.Hypervisor == VSphere {
// Set proxy on RHSM if available
if b.Os == RedHat && b.VsphereConfig.HttpProxy != "" {
if err := setRhsmProxy(&b.VsphereConfig.ProxyConfig, &b.VsphereConfig.RhsmConfig); err != nil {
log.Fatalf("Error parsing proxy host and port for RHSM: %v", err)
}
}

// Read and set the vsphere connection data
vsphereConfigData, err := json.Marshal(b.VsphereConfig)
if err != nil {
Expand All @@ -134,6 +141,8 @@ func (b *BuildOptions) BuildImage() {
commandEnvVars = append(commandEnvVars,
fmt.Sprintf("%s=%s", rhelUsernameEnvVar, b.VsphereConfig.RhelUsername),
fmt.Sprintf("%s=%s", rhelPasswordEnvVar, b.VsphereConfig.RhelPassword),
fmt.Sprintf("%s=%s", rhsmActivationKeyEnvVar, b.VsphereConfig.ActivationKey),
fmt.Sprintf("%s=%s", rhsmOrgIDEnvVar, b.VsphereConfig.OrgId),
)
}

Expand All @@ -151,6 +160,13 @@ func (b *BuildOptions) BuildImage() {

log.Printf("Image Build Successful\n Please find the output artifact at %s\n", outputArtifactPath)
} else if b.Hypervisor == Baremetal {
// Set proxy on RHSM if available
if b.Os == RedHat && b.BaremetalConfig.HttpProxy != "" {
if err := setRhsmProxy(&b.BaremetalConfig.ProxyConfig, &b.BaremetalConfig.RhsmConfig); err != nil {
log.Fatalf("Error parsing proxy host and port for RHSM: %v", err)
}
}

baremetalConfigFile := filepath.Join(imageBuilderProjectPath, packerBaremetalConfigFile)
if b.BaremetalConfig != nil {
baremetalConfigData, err := json.Marshal(b.BaremetalConfig)
Expand All @@ -172,6 +188,8 @@ func (b *BuildOptions) BuildImage() {
commandEnvVars = append(commandEnvVars,
fmt.Sprintf("%s=%s", rhelUsernameEnvVar, b.BaremetalConfig.RhelUsername),
fmt.Sprintf("%s=%s", rhelPasswordEnvVar, b.BaremetalConfig.RhelPassword),
fmt.Sprintf("%s=%s", rhsmActivationKeyEnvVar, b.BaremetalConfig.ActivationKey),
fmt.Sprintf("%s=%s", rhsmOrgIDEnvVar, b.BaremetalConfig.OrgId),
)
}
if b.BaremetalConfig != nil {
Expand Down Expand Up @@ -214,6 +232,13 @@ func (b *BuildOptions) BuildImage() {

log.Printf("Image Build Successful\n Please find the image uploaded under Nutanix Image Service with name %s\n", b.NutanixConfig.ImageName)
} else if b.Hypervisor == CloudStack {
// Set proxy on RHSM if available
if b.Os == RedHat && b.CloudstackConfig.HttpProxy != "" {
if err := setRhsmProxy(&b.CloudstackConfig.ProxyConfig, &b.CloudstackConfig.RhsmConfig); err != nil {
log.Fatalf("Error parsing proxy host and port for RHSM: %v", err)
}
}

// Create config file
cloudstackConfigFile := filepath.Join(imageBuilderProjectPath, packerCloudStackConfigFile)

Expand All @@ -239,6 +264,8 @@ func (b *BuildOptions) BuildImage() {
commandEnvVars = append(commandEnvVars,
fmt.Sprintf("%s=%s", rhelUsernameEnvVar, b.CloudstackConfig.RhelUsername),
fmt.Sprintf("%s=%s", rhelPasswordEnvVar, b.CloudstackConfig.RhelPassword),
fmt.Sprintf("%s=%s", rhsmActivationKeyEnvVar, b.CloudstackConfig.ActivationKey),
fmt.Sprintf("%s=%s", rhsmOrgIDEnvVar, b.CloudstackConfig.OrgId),
)
}
if b.CloudstackConfig != nil {
Expand Down Expand Up @@ -296,6 +323,6 @@ func (b *BuildOptions) BuildImage() {
}

cleanup(buildToolingRepoPath)

log.Print("Build Successful. Output artifacts located at current working directory\n")
}
4 changes: 3 additions & 1 deletion projects/aws/image-builder/builder/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const (
prodEksaReleaseManifestURL string = "https://anywhere-assets.eks.amazonaws.com/releases/eks-a/manifest.yaml"
devEksaReleaseManifestURL string = "https://dev-release-assets.eks-anywhere.model-rocket.aws.dev/eks-a-release.yaml"
devBranchEksaReleaseManifestURL string = "https://dev-release-assets.eks-anywhere.model-rocket.aws.dev/%s/eks-a-release.yaml"

// Environment variables
branchNameEnvVar string = "BRANCH_NAME"
codebuildCIEnvVar string = "CODEBUILD_CI"
Expand All @@ -39,6 +39,8 @@ const (
packerAdditionalFilesConfigFileEnvVar string = "PACKER_ADDITIONAL_FILES_VAR_FILES"
rhelUsernameEnvVar string = "RHSM_USERNAME"
rhelPasswordEnvVar string = "RHSM_PASSWORD"
rhsmActivationKeyEnvVar string = "RHSM_ACTIVATION_KEY"
rhsmOrgIDEnvVar string = "RHSM_ORG_ID"
packerTypeVarFilesEnvVar string = "PACKER_TYPE_VAR_FILES"
eksaUseDevReleaseEnvVar string = "EKSA_USE_DEV_RELEASE"

Expand Down
24 changes: 24 additions & 0 deletions projects/aws/image-builder/builder/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,23 @@ type VsphereConfig struct {
AdditionalFiles []File `json:"files"`
IsoConfig
RhelConfig
ProxyConfig
ExtraPackagesConfig
}

type BaremetalConfig struct {
AdditionalFiles []File `json:"files"`
IsoConfig
RhelConfig
ProxyConfig
ExtraPackagesConfig
}

type CloudstackConfig struct {
AnsibleUserVars string `json:"ansible_user_vars"`
IsoConfig
RhelConfig
ProxyConfig
ExtraPackagesConfig
}

Expand All @@ -95,6 +98,8 @@ type IsoConfig struct {
type RhelConfig struct {
RhelUsername string `json:"rhel_username"`
RhelPassword string `json:"rhel_password"`

RhsmConfig
}

type NutanixConfig struct {
Expand All @@ -107,6 +112,7 @@ type NutanixConfig struct {
NutanixUserName string `json:"nutanix_username"`
NutanixPassword string `json:"nutanix_password"`
NutanixSubnetName string `json:"nutanix_subnet_name"`
ProxyConfig
ExtraPackagesConfig
}

Expand All @@ -122,6 +128,7 @@ type AMIConfig struct {
VolumeSize string `json:"volume_size"`
VolumeType string `json:"volume_type"`

ProxyConfig
ExtraPackagesConfig
}

Expand All @@ -130,3 +137,20 @@ type ExtraPackagesConfig struct {
ExtraRepos string `json:"extra_repos,omitempty"`
ExtraRpms string `json:"extra_rpms,omitempty"`
}

type ProxyConfig struct {
HttpProxy string `json:"http_proxy,omitempty"`
HttpsProxy string `json:"https_proxy,omitempty"`

// This can be set to a comma-delimited list of domains that should be excluded from proxying
NoProxy string `json:"no_proxy,omitempty"`
}

type RhsmConfig struct {
ProxyHostname string `json:"rhsm_server_proxy_hostname,omitempty"`
ProxyPort string `json:"rhsm_server_proxy_port,omitempty"`
ServerHostname string `json:"rhsm_server_hostname,omitempty"`
ServerReleaseVersion string `json:"rhsm_server_release_version,omitempty"`
ActivationKey string `json:"rhsm_activation_key,omitempty"`
OrgId string `json:"rhsm_org_id,omitempty"`
}
44 changes: 37 additions & 7 deletions projects/aws/image-builder/builder/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"fmt"
"io"
"log"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -212,20 +214,48 @@ func getEksAReleasesManifestURL() string {
if eksaReleaseManifest != "" {
return eksaReleaseManifest
}

return prodEksaReleaseManifestURL
}

// using a dev release, allow branch_name env var to
// override manifest url
branchName, ok := os.LookupEnv(branchNameEnvVar)
if !ok {
branchName = mainBranch
}
}

if branchName != mainBranch {
return fmt.Sprintf(devBranchEksaReleaseManifestURL, branchName)
}

return devEksaReleaseManifestURL
return fmt.Sprintf(devBranchEksaReleaseManifestURL, branchName)
}

return devEksaReleaseManifestURL
}

// setRhsmProxy takes the proxy config, parses it and sets the appropriate config on rhsm config
func setRhsmProxy(proxy *ProxyConfig, rhsm *RhsmConfig) error {
if proxy.HttpProxy != "" {
host, port, err := parseUrl(proxy.HttpProxy)
if err != nil {
return err
}
rhsm.ProxyHostname = host
rhsm.ProxyPort = port
}

return nil
}

// parseUrl takes a http endpoint and returns hostname, ports and error
func parseUrl(endpoint string) (string, string, error) {
u, err := url.Parse(endpoint)
if err != nil {
return "", "", err
}

host, port, err := net.SplitHostPort(u.Host)
if err != nil {
return "", "", err
}
return host, port, nil
}
40 changes: 34 additions & 6 deletions projects/aws/image-builder/cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func ValidateInputs(bo *builder.BuildOptions) error {
return err
}
if bo.Os == builder.RedHat {
if err = validateRedhat(bo.VsphereConfig.RhelUsername, bo.VsphereConfig.RhelPassword, bo.VsphereConfig.IsoUrl); err != nil {
if err = validateRedhat(&bo.VsphereConfig.RhelConfig, bo.VsphereConfig.IsoUrl); err != nil {
return err
}
}
Expand All @@ -156,12 +156,15 @@ func ValidateInputs(bo *builder.BuildOptions) error {
return err
}
}
if err = validateRHSM(bo.Os, &bo.VsphereConfig.RhsmConfig); err != nil {
return err
}
case builder.Baremetal:
if err = json.Unmarshal(config, &bo.BaremetalConfig); err != nil {
return err
}
if bo.Os == builder.RedHat {
if err = validateRedhat(bo.BaremetalConfig.RhelUsername, bo.BaremetalConfig.RhelPassword, bo.BaremetalConfig.IsoUrl); err != nil {
if err = validateRedhat(&bo.BaremetalConfig.RhelConfig, bo.BaremetalConfig.IsoUrl); err != nil {
return err
}
}
Expand All @@ -170,6 +173,9 @@ func ValidateInputs(bo *builder.BuildOptions) error {
return err
}
}
if err = validateRHSM(bo.Os, &bo.BaremetalConfig.RhsmConfig); err != nil {
return err
}
case builder.Nutanix:
if err = json.Unmarshal(config, &bo.NutanixConfig); err != nil {
return err
Expand All @@ -184,7 +190,7 @@ func ValidateInputs(bo *builder.BuildOptions) error {
return err
}
if bo.Os == builder.RedHat {
if err = validateRedhat(bo.CloudstackConfig.RhelUsername, bo.CloudstackConfig.RhelPassword, bo.CloudstackConfig.IsoUrl); err != nil {
if err = validateRedhat(&bo.CloudstackConfig.RhelConfig, bo.CloudstackConfig.IsoUrl); err != nil {
return err
}
}
Expand All @@ -193,6 +199,9 @@ func ValidateInputs(bo *builder.BuildOptions) error {
return err
}
}
if err = validateRHSM(bo.Os, &bo.CloudstackConfig.RhsmConfig); err != nil {
return err
}
case builder.AMI:
// Default configuration for AMI builds
amiFilter := builder.DefaultUbuntu2004AMIFilterName
Expand Down Expand Up @@ -260,9 +269,28 @@ func validateOSHypervisorCombinations(os, hypervisor string) error {
return nil
}

func validateRedhat(rhelUsername, rhelPassword, isoUrl string) error {
if rhelUsername == "" || rhelPassword == "" {
return fmt.Errorf("\"rhel_username\" and \"rhel_password\" are required fields in config when os is redhat")
func validateRHSM(os string, rhsmConfig *builder.RhsmConfig) error {
if rhsmConfig.ServerHostname != "" {
if os != builder.RedHat {
return fmt.Errorf("RedHat Subscription Manager Config (RHSM) cannot be provided when OS is not RedHat")
}

if rhsmConfig.ServerReleaseVersion == "" {
return fmt.Errorf("RHSM version required when satelite server hostname is set for RHSM")
}

if rhsmConfig.ActivationKey == "" || rhsmConfig.OrgId == "" {
return fmt.Errorf("Activation key and Org ID are required to use RHSM with satellite")
}
}
return nil
}

func validateRedhat(rhelConfig *builder.RhelConfig, isoUrl string) error {
if rhelConfig.ServerHostname == "" {
if rhelConfig.RhelUsername == "" || rhelConfig.RhelPassword == "" {
return fmt.Errorf("\"rhel_username\" and \"rhel_password\" are required fields in config when os is redhat")
}
}
if isoUrl == "" {
return fmt.Errorf("\"iso_url\" is a required field in config when os is redhat")
Expand Down