Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Enrique Llorente <[email protected]>
  • Loading branch information
qinqon committed Jan 2, 2025
1 parent 2e791f9 commit 120d8b6
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 203 deletions.
2 changes: 1 addition & 1 deletion docs/examples/lldp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
spec:
capture:
ethernets: interfaces.type=="ethernet"
ethernets-up: capture.ethernets | interfaces.state=="up"
ethernets-lldp: capture.ethernets-up | interfaces.lldp.enabled:=true
ethernets-up: capture.ethernets | interfaces.state=="up"
desiredState:
interfaces: "{{ capture.ethernets-lldp.interfaces }}"
112 changes: 31 additions & 81 deletions pkg/nmpolicy/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,105 +18,55 @@ limitations under the License.
package nmpolicy

import (
"github.com/nmstate/nmpolicy/nmpolicy"
nmpolicytypes "github.com/nmstate/nmpolicy/nmpolicy/types"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"encoding/json"

nmstateapi "github.com/nmstate/kubernetes-nmstate/api/shared"
"github.com/nmstate/kubernetes-nmstate/pkg/nmstatectl"
)

type NMPolicyGenerator interface {
GenerateState(
nmpolicySpec nmpolicytypes.PolicySpec,
currentState []byte,
cache nmpolicytypes.CachedState,
) (nmpolicytypes.GeneratedState, error)
}

type GenerateStateWithNMPolicy struct{}

func (GenerateStateWithNMPolicy) GenerateState(
nmpolicySpec nmpolicytypes.PolicySpec,
currentState []byte,
cache nmpolicytypes.CachedState,
) (nmpolicytypes.GeneratedState, error) {
return nmpolicy.GenerateState(nmpolicySpec, currentState, cache)
}

// The method generates the state using the default NMPolicyGenerator
func GenerateState(desiredState nmstateapi.State,
policySpec nmstateapi.NodeNetworkConfigurationPolicySpec,
currentState nmstateapi.State,
cachedState map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState) (
map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState, /* resolved captures */
nmstateapi.State, /* updated desired state */
error) {
return GenerateStateWithStateGenerator(GenerateStateWithNMPolicy{}, desiredState, policySpec, currentState, cachedState)
}

// The method generates the state using NMPolicyGenerator.GenerateState and then converts the returned value to the match the enactment api
func GenerateStateWithStateGenerator(stateGenerator NMPolicyGenerator,
func GenerateState(
desiredState nmstateapi.State,
policySpec nmstateapi.NodeNetworkConfigurationPolicySpec,
currentState nmstateapi.State,
cachedState map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState) (
map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState,
nmstateapi.State, error) {
nmpolicySpec := nmpolicytypes.PolicySpec{
map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState, nmstateapi.State, error) {
if len(desiredState.Raw) == 0 || len(currentState.Raw) == 0 {
return map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{},
nmstateapi.State{}, nil
}
nmstatePolicy := struct {
Capture map[string]string `json:"capture,omitempty"`
DesiredState nmstateapi.State `json:"desiredState,omitempty"`
}{
Capture: policySpec.Capture,
DesiredState: []byte(desiredState.Raw),
DesiredState: policySpec.DesiredState,
}
nmpolicyGeneratedState, err := stateGenerator.GenerateState(
nmpolicySpec,
currentState.Raw,
convertCachedStateFromEnactment(cachedState),
)

nmstatePolicyRaw, err := json.Marshal(nmstatePolicy)
if err != nil {
return map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{},
nmstateapi.State{}, err
}

capturedStates, desiredState := convertGeneratedStateToEnactmentConfig(nmpolicyGeneratedState)
return capturedStates, desiredState, nil
}

func convertGeneratedStateToEnactmentConfig(nmpolicyGeneratedState nmpolicytypes.GeneratedState) (
map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState, nmstateapi.State) {
capturedStates := map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{}

for captureKey, capturedState := range nmpolicyGeneratedState.Cache.Capture {
capturedState := nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{
State: nmstateapi.State{
Raw: []byte(capturedState.State),
},
MetaInfo: convertMetaInfoToEnactment(capturedState.MetaInfo),
cachedStateRaw := []byte{}
if len(cachedState) > 0 {
cachedStateRaw, err = json.Marshal(cachedState)
if err != nil {
return map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{},
nmstateapi.State{}, err
}
capturedStates[captureKey] = capturedState
}
return capturedStates, nmstateapi.State{Raw: []byte(nmpolicyGeneratedState.DesiredState)}
}

func convertCachedStateFromEnactment(
enactmentCachedState map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState,
) nmpolicytypes.CachedState {
cachedState := nmpolicytypes.CachedState{Capture: make(map[string]nmpolicytypes.CaptureState)}
for captureKey, capturedState := range enactmentCachedState {
capturedState := nmpolicytypes.CaptureState{
State: nmpolicytypes.NMState(capturedState.State.Raw),
MetaInfo: nmpolicytypes.MetaInfo{
Version: capturedState.MetaInfo.Version,
TimeStamp: capturedState.MetaInfo.TimeStamp.Time,
},
}
cachedState.Capture[captureKey] = capturedState
output, capturedStateRaw, err := nmstatectl.Policy(nmstatePolicyRaw, []byte(currentState.Raw), cachedStateRaw)
if err != nil {
return map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{},
nmstateapi.State{}, err
}
return cachedState
}

func convertMetaInfoToEnactment(metaInfo nmpolicytypes.MetaInfo) nmstateapi.NodeNetworkConfigurationEnactmentMetaInfo {
return nmstateapi.NodeNetworkConfigurationEnactmentMetaInfo{
Version: metaInfo.Version,
TimeStamp: metav1.NewTime(metaInfo.TimeStamp),
capturedState := map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{}
if err := json.Unmarshal(capturedStateRaw, &capturedState); err != nil {
return map[string]nmstateapi.NodeNetworkConfigurationEnactmentCapturedState{},
nmstateapi.State{}, err
}

return capturedState, nmstateapi.State{Raw: output}, nil
}
111 changes: 0 additions & 111 deletions pkg/nmpolicy/generate_test.go

This file was deleted.

61 changes: 61 additions & 0 deletions pkg/nmstatectl/nmstatectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strconv"
"strings"
Expand Down Expand Up @@ -141,3 +142,63 @@ func Statistic(desiredState nmstate.State) (*Stats, error) {
}
return NewStats(stats.Features), nil
}

func Policy(policy, currentState, capturedState []byte) (desiredState, generatedCapturedState []byte, err error) {
policyFile, err := generateFileWithContent("policy", policy)
if err != nil {
return nil, nil, err
}
defer func() {
os.Remove(policyFile)
}()

args := []string{"policy"}
if len(currentState) > 0 {
var currentStateFile string
currentStateFile, err = generateFileWithContent("currentState", currentState)
if err != nil {
return nil, nil, err
}
defer func() {
os.Remove(currentStateFile)
}()
args = append(args, "--current", currentStateFile)
}

args = append(args, "--json")

capturedStateFile, err := generateFileWithContent("capturedState", capturedState)
if err != nil {
return nil, nil, err
}
defer func() {
os.Remove(capturedStateFile)
}()
args = append(args, "--output-captured", capturedStateFile)
if len(capturedState) > 0 {
args = append(args, "--captured", capturedStateFile)
}

args = append(args, policyFile)
out, err := nmstatectl(args)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed calling nmstatectl rollback")
}
capturedState, err = os.ReadFile(capturedStateFile)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed failed reading captured state")
}
return []byte(out), capturedState, nil
}

func generateFileWithContent(name string, content []byte) (string, error) {
file, err := os.CreateTemp("/tmp", name)
if err != nil {
return "", err
}
defer file.Close()
if _, err := file.Write(content); err != nil {
return "", err
}
return file.Name(), nil
}
15 changes: 5 additions & 10 deletions test/e2e/handler/nnce_conditions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ limitations under the License.
package handler

import (
"fmt"
"sync"
"time"

Expand All @@ -30,14 +29,6 @@ import (
policyconditions "github.com/nmstate/kubernetes-nmstate/test/e2e/policy"
)

func invalidConfig(bridgeName string) nmstate.State {
return nmstate.NewState(fmt.Sprintf(`interfaces:
- name: %s
type: linux-bridge
state: invalid_state
`, bridgeName))
}

var _ = Describe("EnactmentCondition", func() {
Context("when applying valid config", func() {
AfterEach(func() {
Expand Down Expand Up @@ -76,7 +67,11 @@ var _ = Describe("EnactmentCondition", func() {

Context("when applying invalid configuration", func() {
BeforeEach(func() {
updateDesiredState(invalidConfig(bridge1))
updateDesiredState(nmstate.NewState(`interfaces:
- name: bad1
type: ethernet
state: up
`))
})

AfterEach(func() {
Expand Down

0 comments on commit 120d8b6

Please sign in to comment.