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

OCPBUGS-46035: fix skew support for node-joiner #9307

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
74 changes: 74 additions & 0 deletions pkg/asset/agent/joiner/clusterinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,19 @@ func (ci *ClusterInfo) retrieveArchitecture() error {
func (ci *ClusterInfo) retrieveFIPS() error {
workerMachineConfig, err := ci.OpenshiftMachineConfigClient.MachineconfigurationV1().MachineConfigs().Get(context.Background(), "99-worker-fips", metav1.GetOptions{})
if err != nil {
// Older oc client may not have sufficient permissions,
// falling back to previous implementation.
if errors.IsForbidden(err) {
installConfig, err := ci.retrieveInstallConfig()
if err != nil {
if errors.IsNotFound(err) {
return nil
}
return err
}
ci.FIPS = installConfig.FIPS
andfasano marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
// This resource is not created when FIPS is not enabled
if errors.IsNotFound(err) {
return nil
Expand All @@ -273,6 +286,19 @@ func (ci *ClusterInfo) retrieveSSHKey() error {

workerMachineConfig, err := ci.OpenshiftMachineConfigClient.MachineconfigurationV1().MachineConfigs().Get(context.Background(), "99-worker-ssh", metav1.GetOptions{})
if err != nil {
// Older oc client may not have sufficient permissions,
// falling back to previous implementation.
if errors.IsForbidden(err) {
installConfig, err := ci.retrieveInstallConfig()
if err != nil {
if errors.IsNotFound(err) {
return nil
}
return err
}
ci.SSHKey = installConfig.SSHKey
andfasano marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
return err
}
var ign igntypes.Config
Expand All @@ -292,6 +318,11 @@ func (ci *ClusterInfo) retrieveSSHKey() error {
func (ci *ClusterInfo) retrieveWorkerChronyConfig() error {
workerMachineConfig, err := ci.OpenshiftMachineConfigClient.MachineconfigurationV1().MachineConfigs().Get(context.Background(), "50-workers-chrony-configuration", metav1.GetOptions{})
if err != nil {
// Older oc client may not have sufficient permissions,
// falling back to previous implementation.
if errors.IsForbidden(err) {
return nil
}
if errors.IsNotFound(err) {
return nil
}
Expand Down Expand Up @@ -319,9 +350,39 @@ func (ci *ClusterInfo) retrieveBootArtifactsBaseURL() error {
return nil
}

func (ci *ClusterInfo) retrieveInstallConfig() (*types.InstallConfig, error) {
clusterConfig, err := ci.Client.CoreV1().ConfigMaps("kube-system").Get(context.Background(), "cluster-config-v1", metav1.GetOptions{})
if err != nil {
return nil, err
}
data, ok := clusterConfig.Data["install-config"]
if !ok {
return nil, fmt.Errorf("cannot find install-config data")
}

installConfig := types.InstallConfig{}
if err = yaml.Unmarshal([]byte(data), &installConfig); err != nil {
return nil, err
}
return &installConfig, nil
}

func (ci *ClusterInfo) retrieveImageDigestMirrorSets() error {
imageDigestMirrorSets, err := ci.OpenshiftClient.ConfigV1().ImageDigestMirrorSets().List(context.Background(), metav1.ListOptions{})
if err != nil {
// Older oc client may not have sufficient permissions,
// falling back to previous implementation.
if errors.IsForbidden(err) {
installConfig, err := ci.retrieveInstallConfig()
if err != nil {
if errors.IsNotFound(err) {
return nil
}
return err
}
ci.ImageDigestSources = installConfig.ImageDigestSources
return nil
}
if !errors.IsNotFound(err) {
return err
}
Expand All @@ -346,6 +407,19 @@ func (ci *ClusterInfo) retrieveImageDigestMirrorSets() error {
func (ci *ClusterInfo) retrieveImageContentPolicies() error {
imageContentPolicies, err := ci.OpenshiftClient.ConfigV1().ImageContentPolicies().List(context.Background(), metav1.ListOptions{})
if err != nil {
// Older oc client may not have sufficient permissions,
// falling back to previous implementation.
if errors.IsForbidden(err) {
installConfig, err := ci.retrieveInstallConfig()
if err != nil {
if errors.IsNotFound(err) {
return nil
}
return err
}
ci.DeprecatedImageContentSources = installConfig.DeprecatedImageContentSources
andfasano marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
if !errors.IsNotFound(err) {
return err
}
Expand Down
130 changes: 130 additions & 0 deletions pkg/asset/agent/joiner/clusterinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ package joiner
import (
"context"
"encoding/json"
"fmt"
"testing"

ignutil "github.com/coreos/ignition/v2/config/util"
igntypes "github.com/coreos/ignition/v2/config/v3_2/types"
"github.com/coreos/stream-metadata-go/stream"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes/fake"
faketesting "k8s.io/client-go/testing"
"k8s.io/utils/ptr"
"sigs.k8s.io/yaml"

configv1 "github.com/openshift/api/config/v1"
machineconfigv1 "github.com/openshift/api/machineconfiguration/v1"
Expand All @@ -27,13 +32,21 @@ import (
)

func TestClusterInfo_Generate(t *testing.T) {
type fakeClientErr struct {
verb string
resource string
name string
err error
}

cases := []struct {
name string
workflow workflow.AgentWorkflowType
nodesConfig AddNodesConfig
objs func(t *testing.T) ([]runtime.Object, []runtime.Object, []runtime.Object)
overrideExpectedClusterInfo func(clusterInfo ClusterInfo) ClusterInfo
expectedError string
fakeClientError *fakeClientErr
}{
{
name: "skip if not add-nodes workflow",
Expand Down Expand Up @@ -150,6 +163,59 @@ storage:
return clusterInfo
},
},
{
name: "fallback for icsp",
workflow: workflow.AgentWorkflowTypeAddNodes,
objs: defaultObjects(),
fakeClientError: &fakeClientErr{
verb: "list",
resource: "imagecontentpolicies",
err: errors.NewForbidden(schema.GroupResource{}, "", nil),
},
},
{
name: "fallback for idms",
workflow: workflow.AgentWorkflowTypeAddNodes,
objs: defaultObjects(),
fakeClientError: &fakeClientErr{
verb: "list",
resource: "imagedigestmirrorsets",
err: errors.NewForbidden(schema.GroupResource{}, "", nil),
},
},
{
name: "fallback for chrony (skipped)",
workflow: workflow.AgentWorkflowTypeAddNodes,
objs: defaultObjects(),
fakeClientError: &fakeClientErr{
verb: "get",
resource: "machineconfigs",
name: "50-workers-chrony-configuration",
err: errors.NewForbidden(schema.GroupResource{}, "", nil),
},
},
{
name: "fallback for fips",
workflow: workflow.AgentWorkflowTypeAddNodes,
objs: defaultObjects(),
fakeClientError: &fakeClientErr{
verb: "get",
resource: "machineconfigs",
name: "99-worker-fips",
err: errors.NewForbidden(schema.GroupResource{}, "", nil),
},
},
{
name: "fallback for ssh",
workflow: workflow.AgentWorkflowTypeAddNodes,
objs: defaultObjects(),
fakeClientError: &fakeClientErr{
verb: "get",
resource: "machineconfigs",
name: "99-worker-ssh",
err: errors.NewForbidden(schema.GroupResource{}, "", nil),
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
Expand All @@ -167,6 +233,35 @@ storage:
fakeOCClient := fakeclientconfig.NewSimpleClientset(openshiftObjects...)
fakeOCMachineConfigClient := fakeclientmachineconfig.NewSimpleClientset(openshiftMachineConfigObjects...)

if tc.fakeClientError != nil {
switch tc.fakeClientError.resource {
case "machineconfigs":
fakeOCMachineConfigClient.PrependReactor(tc.fakeClientError.verb, tc.fakeClientError.resource, func(action faketesting.Action) (handled bool, ret runtime.Object, err error) {
getAction, ok := action.(faketesting.GetAction)
if ok && getAction.GetName() == tc.fakeClientError.name {
return true, nil, errors.NewForbidden(
schema.GroupResource{Group: "", Resource: tc.fakeClientError.resource},
tc.fakeClientError.name,
fmt.Errorf("access denied"),
)
}
return false, nil, nil
})
case "imagedigestmirrorsets", "imagecontentpolicies":
fakeOCClient.PrependReactor(tc.fakeClientError.verb, tc.fakeClientError.resource, func(action faketesting.Action) (handled bool, ret runtime.Object, err error) {
listAction, ok := action.(faketesting.ListAction)
if ok && listAction.GetResource().Resource == tc.fakeClientError.resource {
return true, nil, errors.NewForbidden(
schema.GroupResource{Group: "", Resource: tc.fakeClientError.resource},
tc.fakeClientError.name,
fmt.Errorf("access denied"),
)
}
return false, nil, nil
})
}
}

clusterInfo := ClusterInfo{
Client: fakeClient,
OpenshiftClient: fakeOCClient,
Expand Down Expand Up @@ -233,6 +328,32 @@ func makeCoreOsBootImages(t *testing.T, st *stream.Stream) string {
return string(data)
}

func makeInstallConfig(t *testing.T) string {
t.Helper()
ic := &types.InstallConfig{
ObjectMeta: v1.ObjectMeta{
Name: "ostest",
},
BaseDomain: "test.metalkube.org",
ImageDigestSources: []types.ImageDigestSource{
{
Source: "quay.io/openshift-release-dev/ocp-v4.0-art-dev",
Mirrors: []string{
"registry.example.com:5000/ocp4/openshift4",
},
},
},
SSHKey: "my-ssh-key",
FIPS: true,
}
data, err := yaml.Marshal(ic)
if err != nil {
t.Error(err)
}

return string(data)
}

func defaultObjects() func(t *testing.T) ([]runtime.Object, []runtime.Object, []runtime.Object) {
return func(t *testing.T) ([]runtime.Object, []runtime.Object, []runtime.Object) {
t.Helper()
Expand Down Expand Up @@ -267,6 +388,15 @@ func defaultObjects() func(t *testing.T) ([]runtime.Object, []runtime.Object, []
},
},
},
&corev1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Name: "cluster-config-v1",
Namespace: "kube-system",
},
Data: map[string]string{
"install-config": makeInstallConfig(t),
},
},
&corev1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Name: "coreos-bootimages",
Expand Down