-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Micah Hausler <mhausler@amazon.com>
- Loading branch information
1 parent
0199cbc
commit 4282254
Showing
14 changed files
with
778 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package kubernetes | ||
|
||
import ( | ||
"context" | ||
"net" | ||
|
||
"github.com/packethost/pkg/log" | ||
"github.com/pkg/errors" | ||
"github.com/tinkerbell/boots/client" | ||
"github.com/tinkerbell/tink/pkg/apis/core/v1alpha1" | ||
"github.com/tinkerbell/tink/pkg/controllers" | ||
"github.com/tinkerbell/tink/pkg/convert" | ||
"github.com/tinkerbell/tink/protos/workflow" | ||
"k8s.io/client-go/tools/clientcmd" | ||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | ||
crclient "sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
// HardwareFinder is a type that looks up hardware from Kubernetes | ||
type HardwareFinder struct { | ||
clientFunc func() crclient.Client | ||
logger log.Logger | ||
namespace string | ||
} | ||
|
||
// NewHardwareFinder returns a HardwareFinder that discovers hardware from Kubernetes. | ||
func NewHardwareFinder(logger log.Logger, k8sAPI, kubeconfig string) (*HardwareFinder, error) { | ||
ccfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( | ||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}, | ||
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: k8sAPI}}) | ||
|
||
config, err := ccfg.ClientConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
namespace, _, err := ccfg.Namespace() | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
|
||
manager, err := controllers.NewManager(config, controllers.GetServerOptions()) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
|
||
go manager.Start(context.Background()) | ||
|
||
return &HardwareFinder{ | ||
clientFunc: manager.GetClient, | ||
logger: logger, | ||
namespace: namespace, | ||
}, nil | ||
} | ||
|
||
// ByIP returns a Discoverer for a particular IP. | ||
func (f *HardwareFinder) ByIP(ctx context.Context, ip net.IP) (client.Discoverer, error) { | ||
hardwareList := &v1alpha1.HardwareList{} | ||
|
||
err := f.clientFunc().List(ctx, hardwareList, &crclient.MatchingFields{ | ||
controllers.HardwareIPAddrIndex: ip.String(), | ||
}) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed listing hardware") | ||
} | ||
|
||
if len(hardwareList.Items) == 0 { | ||
return nil, errors.New("no hardware found") | ||
} | ||
|
||
if len(hardwareList.Items) > 1 { | ||
return nil, errors.Errorf("got %d hardware for ip %s, expected only 1", len(hardwareList.Items), ip) | ||
} | ||
|
||
return NewK8sDiscoverer(&hardwareList.Items[0]), nil | ||
} | ||
|
||
// ByMAC returns a Discoverer for a particular MAC address. | ||
func (f *HardwareFinder) ByMAC(ctx context.Context, mac net.HardwareAddr, _ net.IP, _ string) (client.Discoverer, error) { | ||
hardwareList := &v1alpha1.HardwareList{} | ||
|
||
err := f.clientFunc().List(ctx, hardwareList, &crclient.MatchingFields{ | ||
controllers.HardwareMACAddrIndex: mac.String(), | ||
}) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed listing hardware") | ||
} | ||
|
||
if len(hardwareList.Items) == 0 { | ||
return nil, errors.New("no hardware found") | ||
} | ||
|
||
if len(hardwareList.Items) > 1 { | ||
return nil, errors.Errorf("got %d hardware for mac %s, expected only 1", len(hardwareList.Items), mac) | ||
} | ||
|
||
return NewK8sDiscoverer(&hardwareList.Items[0]), nil | ||
} | ||
|
||
// WorkflowFinder is a type for finding if a hardware ID has active workflows. | ||
type WorkflowFinder struct { | ||
clientFunc func() crclient.Client | ||
logger log.Logger | ||
namespace string | ||
} | ||
|
||
// NewWorkflowFinder returns a *WorkflowFinder that satisfies client.WorkflowFinder. | ||
func NewWorkflowFinder(logger log.Logger, k8sAPI, kubeconfig string) (*WorkflowFinder, error) { | ||
ccfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( | ||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}, | ||
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: k8sAPI}}) | ||
|
||
config, err := ccfg.ClientConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
namespace, _, err := ccfg.Namespace() | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
|
||
manager, err := controllers.NewManager(config, controllers.GetServerOptions()) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
|
||
go manager.Start(context.Background()) | ||
|
||
return &WorkflowFinder{ | ||
clientFunc: manager.GetClient, | ||
logger: logger, | ||
namespace: namespace, | ||
}, nil | ||
} | ||
|
||
// HasActiveWorkflow finds if an active workflow exists for a particular hardware ID. | ||
func (f *WorkflowFinder) HasActiveWorkflow(ctx context.Context, hwID client.HardwareID) (bool, error) { | ||
if hwID == "" { | ||
return false, errors.New("missing hardware id") | ||
} | ||
|
||
// labels := prometheus.Labels{"from": "dhcp"} | ||
// cacherTimer := prometheus.NewTimer(metrics.CacherDuration.With(labels)) | ||
// metrics.CacherRequestsInProgress.With(labels).Inc() | ||
// metrics.CacherTotal.With(labels).Inc() | ||
stored := &v1alpha1.WorkflowList{} | ||
err := f.clientFunc().List(ctx, stored, &crclient.MatchingFields{ | ||
controllers.WorkflowWorkerNonTerminalStateIndex: hwID.String(), | ||
}) | ||
if err != nil { | ||
return false, errors.Wrap(err, "failed to list workflows") | ||
} | ||
|
||
wfContexts := []*workflow.WorkflowContext{} | ||
for _, wf := range stored.Items { | ||
wfContexts = append(wfContexts, convert.WorkflowToWorkflowContext(&wf)) | ||
} | ||
|
||
wcl := &workflow.WorkflowContextList{ | ||
WorkflowContexts: wfContexts, | ||
} | ||
// cacherTimer.ObserveDuration() | ||
// metrics.CacherRequestsInProgress.With(labels).Dec() | ||
|
||
for _, wf := range (*wcl).WorkflowContexts { | ||
if wf.CurrentActionState == workflow.State_STATE_PENDING || wf.CurrentActionState == workflow.State_STATE_RUNNING { | ||
return true, nil | ||
} | ||
} | ||
|
||
return false, nil | ||
} |
Oops, something went wrong.