From 545f238336e966bf8780f19c7b9285a6e665bd2a Mon Sep 17 00:00:00 2001 From: Avery Carty Date: Thu, 4 Mar 2021 18:14:35 -0500 Subject: [PATCH] updated --- examples/lang/ipport.mcl | 12 +++++ lang/funcs/core/net/ip_port.go | 58 ++++++++++++++++++++++ lang/funcs/core/net/ip_port_test.go | 76 +++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 examples/lang/ipport.mcl create mode 100644 lang/funcs/core/net/ip_port.go create mode 100644 lang/funcs/core/net/ip_port_test.go diff --git a/examples/lang/ipport.mcl b/examples/lang/ipport.mcl new file mode 100644 index 0000000000..846b6b7733 --- /dev/null +++ b/examples/lang/ipport.mcl @@ -0,0 +1,12 @@ +import "net" + +$ipport = net.ip_port("192.168.1.1", "433") + +print "ipport" { + msg => $ipport, +} + +file "/tmp/mgmt/ipport" { + state => $const.res.file.state.exists, + content => $ipport, +} diff --git a/lang/funcs/core/net/ip_port.go b/lang/funcs/core/net/ip_port.go new file mode 100644 index 0000000000..9fdabcfb83 --- /dev/null +++ b/lang/funcs/core/net/ip_port.go @@ -0,0 +1,58 @@ +// Mgmt +// Copyright (C) 2013-2021+ James Shubin and the project contributors +// Written by James Shubin and the project contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package corenet + +import ( + "errors" + "fmt" + "net" + "strconv" + + "github.com/purpleidea/mgmt/lang/funcs/simple" + "github.com/purpleidea/mgmt/lang/types" +) + +func init() { + simple.ModuleRegister(ModuleName, "ip_port", &types.FuncValue{ + T: types.NewType("func(ip str, port str) str"), + V: IPPort, + }) +} + +// IPPort returns the combind IPv4/IPv6:(input[0]) and Port:(input[1]). Returns +// error if IPv4/IPv6 string is incorrect format or Port not in range 0-65536. +func IPPort(input []types.Value) (types.Value, error) { + ip := net.ParseIP(input[0].Str()) // Is nil if incorrect format. + ipStr := input[0].Str() + port := input[1].Str() + portInt, err := strconv.Atoi(port) + + if ip == nil { + return &types.StrValue{V: ""}, errors.New("incorrect ip format") + } + if err != nil { + return &types.StrValue{V: ""}, fmt.Errorf("err converting str to int %v", err) + } + if portInt < 0 || portInt > 65536 { + return &types.StrValue{V: ""}, errors.New("port not in range 0-65536") + } + + return &types.StrValue{ + V: ipStr + ":" + port, + }, nil +} diff --git a/lang/funcs/core/net/ip_port_test.go b/lang/funcs/core/net/ip_port_test.go new file mode 100644 index 0000000000..9d8d75eec7 --- /dev/null +++ b/lang/funcs/core/net/ip_port_test.go @@ -0,0 +1,76 @@ +// Mgmt +// Copyright (C) 2013-2021+ James Shubin and the project contributors +// Written by James Shubin and the project contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package corenet + +import ( + "errors" + "testing" + + "github.com/purpleidea/mgmt/lang/types" +) + +func TestIPPort(t *testing.T) { + ipporttests := []struct { + name string + ip string + port string + expected string + err error + }{ + // Success + {"correct ipv4 and port", "192.168.1.1", "80", "192.168.1.1:80", nil}, + {"correct ipv6 and port", "2345:0425:2CA1:0000:0000:0567:5673:23b5", "8080", "2345:0425:2CA1:0000:0000:0567:5673:23b5:8080", nil}, + {"correct ipv4 and port - allow port 0", "192.168.1.1", "0", "192.168.1.1:0", nil}, + {"correct ipv6 and port - allows port 65536", "2345:0425:2CA1::0567:5673:23b5", "65536", "2345:0425:2CA1::0567:5673:23b5:65536", nil}, + // Fail + {"incorrect ipv4 - octet over 255", "392.868.11.79", "80", "", errors.New("incorrect ip format")}, + {"incorrect ipv4 - CIDR format", "10.10.10.100/8", "23", "", errors.New("incorrect ip format")}, + {"incorrect ipv4 - dots...", "172.16.10..254", "23", "", errors.New("incorrect ip format")}, + {"incorrect ipv6 - double double colon", "5678:A425:2CA1::0567::5673:23b5", "80", "", errors.New("incorrect ip format")}, + {"incorrect ipv6 - non hex chars", "M678:Z425:2CA1::05X7:T673:23b5", "1234", "", errors.New("incorrect ip format")}, + {"incorrect port - outside of range", "192.168.1.1", "65537", "", errors.New("port not in range 0-65536")}, + {"incorrect port - negative port number", "192.168.1.1", "-9483670", "", errors.New("port not in range 0-65536")}, + } + + for _, test := range ipporttests { + t.Run(test.name, func(t *testing.T) { + output, err := IPPort([]types.Value{ + &types.StrValue{V: test.ip}, + &types.StrValue{V: test.port}, + }) + expectedStr := &types.StrValue{V: test.expected} + + if test.err != nil && err.Error() != test.err.Error() { + t.Errorf("ip: %s, port %s, expected error: %q, got %q", test.ip, test.port, test.err, err) + return + } else if test.err != nil && err == nil { + t.Errorf("ip: %s, port: %s, expected error: %v, but got nil", test.ip, test.port, test.err) + return + } else if test.err == nil && err != nil { + t.Errorf("ip: %s, port %s, did not expect error but got: %#v", test.ip, test.port, err) + return + } + if err1 := output.Cmp(expectedStr); err1 != nil { + t.Errorf("ip: %s, port: %s, expected: %s, got: %s", test.ip, test.port, expectedStr, output) + return + } + + }) + } + +}