This commit is contained in:
Jeffrey C. Ollie 2024-05-14 15:23:31 -05:00
parent 866a655ca1
commit 2e68db33aa
Signed by: jeff
GPG key ID: 6F86035A6D97044E
8 changed files with 325 additions and 333 deletions

View file

@ -54,15 +54,15 @@ pub fn build(b: *std.Build) void {
exe.root_module.addImport("anzi", anzi.module("anzi"));
const netboxz = b.dependency(
"netboxz",
.{
.target = target,
.optimize = optimize,
},
);
// const netboxz = b.dependency(
// "netboxz",
// .{
// .target = target,
// .optimize = optimize,
// },
// );
exe.root_module.addImport("netboxz", netboxz.module("netboxz"));
// exe.root_module.addImport("netboxz", netboxz.module("netboxz"));
const logz = b.dependency(
"logz",

View file

@ -4,21 +4,23 @@
.minimum_zig_version = "0.12.0",
.dependencies = .{
.logz = .{
.url = "https://github.com/karlseguin/log.zig/archive/eb86766b91cf2ca0a6e87dd8568fab80695cf2e8.tar.gz",
.hash = "1220b6cf56de826aead943a6db2a62ed40d81a150c24dcb019b3eb88673c82a6e7b7",
.url = "https://github.com/karlseguin/log.zig/archive/2f17be4b6bbd32884df562a8d0501c15ec3bb928.tar.gz",
// .hash = "1220b6cf56de826aead943a6db2a62ed40d81a150c24dcb019b3eb88673c82a6e7b7",
.hash = "1220347c287af8b265e36cffaf1c29e22da887e8fdcf38310e7b7d3c65ce64acf4f0",
},
.anzi = .{
.url = "https://git.ocjtech.us/jeff/anzi/archive/0e9d395a55b16da1d5bf7bfb59e2cfa59a7f2630.tar.gz",
.hash = "12203f0ed986047bcd860b00496979a7734c2f462da4e56a72add4b17a1a7981f8ec",
},
.netboxz = .{
// .url = "https://github.com/jcollie/netboxz/archive/354caea69a1e033cf34da6c5e514dc4eb755af06.tar.gz",
// .hash = "1220374f4587ec4d1e820a45039cd4bedd7cd560a3a668fdae2db0b5a6609f97c793",
.path = "../netboxz",
},
// .netboxz = .{
// // .url = "https://github.com/jcollie/netboxz/archive/354caea69a1e033cf34da6c5e514dc4eb755af06.tar.gz",
// // .hash = "1220374f4587ec4d1e820a45039cd4bedd7cd560a3a668fdae2db0b5a6609f97c793",
// .path = "../netboxz",
// },
.@"zig-cli" = .{
.url = "https://github.com/sam701/zig-cli/archive/50201f0086da689cd104c2fef350f3dbe894eea7.tar.gz",
.hash = "12208a4377c7699927605e5a797bad5ae2ba8be4b49f68b9f522b3a755597a21f1cf",
.url = "https://github.com/sam701/zig-cli/archive/9a94c4803a52e54c26b198096d63fb5bde752da2.tar.gz",
// .hash = "12208a4377c7699927605e5a797bad5ae2ba8be4b49f68b9f522b3a755597a21f1cf",
.hash = "1220ab73fb7cc11b2308edc3364988e05efcddbcac31b707f55e6216d1b9c0da13f1",
},
},
.paths = .{

View file

@ -9,7 +9,7 @@ pub const Config = struct {
name: []const u8,
type: ConnectionType,
comment: []const u8,
addresses: [][]const u8,
address: []const u8,
port: u16,
username: []const u8,
manufacturer: []const u8,
@ -31,13 +31,14 @@ pub const Config = struct {
.name = try alloc.dupe(u8, self.name),
.type = self.type,
.comment = try alloc.dupe(u8, self.comment),
.addresses = addr: {
var addrs = try alloc.alloc([]const u8, self.addresses.len);
for (self.addresses, 0..) |a, i| {
addrs[i] = try alloc.dupe(u8, a);
}
break :addr addrs;
},
.address = try alloc.dupe(u8, self.address),
// .addresses = addr: {
// var addrs = try alloc.alloc([]const u8, self.addresses.len);
// for (self.addresses, 0..) |a, i| {
// addrs[i] = try alloc.dupe(u8, a);
// }
// break :addr addrs;
// },
.port = self.port,
.username = try alloc.dupe(u8, self.username),
.manufacturer = try alloc.dupe(u8, self.manufacturer),

View file

@ -147,6 +147,6 @@ pub fn connect() !void {
);
try bw.flush();
const envp = @as([*:null]const ?[*:0]const u8, @ptrCast(std.os.environ.ptr));
return std.os.execveZ(pathZ, argsZ, envp);
return std.posix.execveZ(pathZ, argsZ, envp);
}
}

View file

@ -2,8 +2,9 @@ const std = @import("std");
const builtin = @import("builtin");
const build_options = @import("build_options");
const cli = @import("zig-cli");
const connect = @import("connect.zig");
const options = @import("options.zig");
const connect = @import("connect.zig");
const update = @import("update.zig");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
@ -11,5 +12,73 @@ pub fn main() !void {
options.options.alloc = alloc;
return cli.run(options.app, alloc);
var r = try cli.AppRunner.init(alloc);
const app = cli.App{
.command = cli.Command{
.name = "hostapps",
.description = cli.Description{
.one_line = "hostapps",
},
.target = cli.CommandTarget{
.subcommands = &.{
cli.Command{
.name = "connect",
.description = cli.Description{
.one_line = "connect",
},
.options = &.{
cli.Option{
.long_name = "config",
.help = "config file",
.value_ref = r.mkRef(&options.options.config),
.required = true,
},
cli.Option{
.long_name = "identity",
.help = "ssh identity",
.value_ref = r.mkRef(&options.options.identities),
},
cli.Option{
.long_name = "proxy-jump",
.help = "proxy jump",
.value_ref = r.mkRef(&options.options.proxy_jump),
},
cli.Option{
.long_name = "ssh-command",
.help = "ssh command",
.value_ref = r.mkRef(&options.options.ssh_path),
},
cli.Option{
.long_name = "telnet-command",
.help = "telnet command",
.value_ref = r.mkRef(&options.options.telnet_path),
},
},
.target = cli.CommandTarget{
.action = cli.CommandAction{
.exec = connect.connect,
},
},
},
cli.Command{
.name = "update",
.description = cli.Description{
.one_line = "update",
},
.options = &.{},
.target = cli.CommandTarget{
.action = cli.CommandAction{
.exec = update.update,
},
},
},
},
},
},
.version = "0.1.0",
.author = "Jeffrey C. Ollie <jcollie@dmacc.edu>",
};
return r.run(&app);
}

View file

@ -17,83 +17,3 @@ pub var options: Options = .{
.ssh_path = build_options.ssh_path,
.telnet_path = build_options.telnet_path,
};
var config_option = cli.Option{
.long_name = "config",
.help = "config file",
.value_ref = cli.mkRef(&options.config),
.required = true,
};
var identity_option = cli.Option{
.long_name = "identity",
.help = "ssh identity",
.value_ref = cli.mkRef(&options.identities),
};
var proxy_jump_option = cli.Option{
.long_name = "proxy-jump",
.help = "proxy jump",
.value_ref = cli.mkRef(&options.proxy_jump),
};
var ssh_command_option = cli.Option{
.long_name = "ssh-command",
.help = "ssh command",
.value_ref = cli.mkRef(&options.ssh_path),
};
var telnet_command_option = cli.Option{
.long_name = "telnet-command",
.help = "telnet command",
.value_ref = cli.mkRef(&options.telnet_path),
};
var connect_command = cli.Command{
.name = "connect",
.description = cli.Description{
.one_line = "connect",
},
.options = &.{
&config_option,
&identity_option,
&proxy_jump_option,
&ssh_command_option,
&telnet_command_option,
},
.target = cli.CommandTarget{
.action = cli.CommandAction{
.exec = connect.connect,
},
},
};
var update_command = cli.Command{
.name = "update",
.description = cli.Description{
.one_line = "update",
},
.options = &.{},
.target = cli.CommandTarget{
.action = cli.CommandAction{
.exec = update.update,
},
},
};
pub const app = &cli.App{
.command = cli.Command{
.name = "hostapps",
.description = cli.Description{
.one_line = "hostapps",
},
.target = cli.CommandTarget{
.subcommands = &.{
&connect_command,
&update_command,
},
},
},
.version = "0.1.0",
.author = "Jeffrey C. Ollie <jcollie@dmacc.edu>",
};

View file

@ -8,7 +8,7 @@ pub fn expandPath(alloc: std.mem.Allocator, cmd: []const u8) !?[]u8 {
const path = try std.unicode.utf16leToUtf8Alloc(alloc, win_path);
break :blk path;
},
else => std.os.getenvZ("PATH") orelse return null,
else => std.posix.getenvZ("PATH") orelse return null,
};
defer if (builtin.os.tag == .windows) alloc.free(PATH);

View file

@ -4,245 +4,245 @@ const Config = @import("config.zig").Config;
const ConnectionType = @import("config.zig").ConnectionType;
const options = @import("options.zig");
const ansi = @import("anzi").ANSI(.{});
const netboxz = @import("netboxz");
// const netboxz = @import("netboxz");
const HashMap = @import("hashmap");
const log = std.log.scoped(.update);
pub fn update() !void {
var arena = std.heap.ArenaAllocator.init(options.options.alloc);
const alloc = arena.allocator();
defer arena.deinit();
// var arena = std.heap.ArenaAllocator.init(options.options.alloc);
// const alloc = arena.allocator();
// defer arena.deinit();
const nb = try netboxz.init(alloc, "https://netbox.dmacc.net", "814e66254d019e7ef37de53bacc8e88e411da855");
// const nb = try netboxz.init(alloc, "https://", "");
const mfg_cisco_id = id: {
var one = try nb.dcim().manufacturers().one(
&[_]netboxz.FilterOperation{
.{
.string = .{
.key = "name",
.value = "Cisco",
.comparison = .eq,
},
},
},
);
defer one.deinit();
log.info("one: {any}", .{one.ok.value.name});
switch (one) {
.ok => |r| {
log.info("found manufacturer {d} {s}", .{ r.value.id, r.value.name });
break :id r.value.id;
},
.notfound => {
log.err("could not find Cisco", .{});
return;
},
.toomany => |r| {
log.err("{} is too many", .{r.count});
return;
},
.err => |r| {
log.err("error from netbox: {s}", .{r.detail});
return;
},
}
};
// const mfg_cisco_id = id: {
// var one = try nb.dcim().manufacturers().one(
// &[_]netboxz.FilterOperation{
// .{
// .string = .{
// .key = "name",
// .value = "Cisco",
// .comparison = .eq,
// },
// },
// },
// );
// defer one.deinit();
// log.info("one: {any}", .{one.ok.value.name});
// switch (one) {
// .ok => |r| {
// log.info("found manufacturer {d} {s}", .{ r.value.id, r.value.name });
// break :id r.value.id;
// },
// .notfound => {
// log.err("could not find Cisco", .{});
// return;
// },
// .toomany => |r| {
// log.err("{} is too many", .{r.count});
// return;
// },
// .err => |r| {
// log.err("error from netbox: {s}", .{r.detail});
// return;
// },
// }
// };
log.info("found mfg id {}", .{mfg_cisco_id});
// log.info("found mfg id {}", .{mfg_cisco_id});
const network_role_id = id: {
var one = try nb.dcim().device_roles().one(
&[_]netboxz.FilterOperation{
.{
.string = .{
.key = "name",
.value = "Network",
.comparison = .eq,
},
},
},
);
defer one.deinit();
switch (one) {
.ok => |r| {
break :id r.value.id;
},
.notfound => {
log.err("could not find Network", .{});
return;
},
.toomany => |r| {
log.err("{} is too many", .{r.count});
return;
},
.err => |r| {
log.err("error from netbox: {s}", .{r.detail});
return;
},
}
};
// const network_role_id = id: {
// var one = try nb.dcim().device_roles().one(
// &[_]netboxz.FilterOperation{
// .{
// .string = .{
// .key = "name",
// .value = "Network",
// .comparison = .eq,
// },
// },
// },
// );
// defer one.deinit();
// switch (one) {
// .ok => |r| {
// break :id r.value.id;
// },
// .notfound => {
// log.err("could not find Network", .{});
// return;
// },
// .toomany => |r| {
// log.err("{} is too many", .{r.count});
// return;
// },
// .err => |r| {
// log.err("error from netbox: {s}", .{r.detail});
// return;
// },
// }
// };
log.info("found role id {}", .{network_role_id});
// log.info("found role id {}", .{network_role_id});
{
var iter = try nb.dcim().devices().list(
.{
.filters = &[_]netboxz.FilterOperation{
.{
.fk = .{
.key = "manufacturer_id",
.value = mfg_cisco_id,
},
},
.{
.fk = .{
.key = "role_id",
.value = network_role_id,
},
},
.{
.choice = .{
.key = "status",
.value = "active",
},
},
.{
.boolean = .{
.key = "has_primary_ip",
.value = true,
},
},
},
},
);
// {
// var iter = try nb.dcim().devices().list(
// .{
// .filters = &[_]netboxz.FilterOperation{
// .{
// .fk = .{
// .key = "manufacturer_id",
// .value = mfg_cisco_id,
// },
// },
// .{
// .fk = .{
// .key = "role_id",
// .value = network_role_id,
// },
// },
// .{
// .choice = .{
// .key = "status",
// .value = "active",
// },
// },
// .{
// .boolean = .{
// .key = "has_primary_ip",
// .value = true,
// },
// },
// },
// },
// );
var part_number_map = HashMap.init(alloc);
// var part_number_map = HashMap.init(alloc);
while (try iter.next()) |device_result| {
defer device_result.deinit();
// while (try iter.next()) |device_result| {
// defer device_result.deinit();
switch (device_result) {
.ok => |devices| {
for (devices.items) |device| {
const name = name: {
if (device.virtual_chassis) |vc| break :name vc.name;
if (device.name) |name| break :name name;
break :name device.display;
};
log.info("found device {d} '{s}' '{s}'", .{ device.id, name, device.display });
const part_number = pn: {
if (part_number_map.get(device.device_type.id)) |pn| break :pn pn;
const pn_result = try device.device_type.full(nb);
switch (pn_result) {
.ok => |r| {
part_number_map.put(r.item.id, r.item.part_number);
break :pn r.item.part_number;
},
.err => |r| {
log.err("error: {}", .{r.detail});
return;
},
}
};
// switch (device_result) {
// .ok => |devices| {
// for (devices.items) |device| {
// const name = name: {
// if (device.virtual_chassis) |vc| break :name vc.name;
// if (device.name) |name| break :name name;
// break :name device.display;
// };
// log.info("found device {d} '{s}' '{s}'", .{ device.id, name, device.display });
// const part_number = pn: {
// if (part_number_map.get(device.device_type.id)) |pn| break :pn pn;
// const pn_result = try device.device_type.full(nb);
// switch (pn_result) {
// .ok => |r| {
// part_number_map.put(r.item.id, r.item.part_number);
// break :pn r.item.part_number;
// },
// .err => |r| {
// log.err("error: {}", .{r.detail});
// return;
// },
// }
// };
var service_iter = try nb.ipam().services().list(
.{
.filters = &[_]netboxz.FilterOperation{
.{
.fk = .{
.key = "device_id",
.value = device.id,
},
},
.{
.string = .{
.key = "name",
.value = "ssh",
.comparison = .ie,
},
},
.{
.string = .{
.key = "name",
.value = "telnet",
.comparison = .ie,
},
},
},
},
);
defer service_iter.deinit();
// var service_iter = try nb.ipam().services().list(
// .{
// .filters = &[_]netboxz.FilterOperation{
// .{
// .fk = .{
// .key = "device_id",
// .value = device.id,
// },
// },
// .{
// .string = .{
// .key = "name",
// .value = "ssh",
// .comparison = .ie,
// },
// },
// .{
// .string = .{
// .key = "name",
// .value = "telnet",
// .comparison = .ie,
// },
// },
// },
// },
// );
// defer service_iter.deinit();
while (try service_iter.next()) |service_result| {
defer service_result.deinit();
// while (try service_iter.next()) |service_result| {
// defer service_result.deinit();
switch (service_result) {
.ok => |services| {
for (services.items) |service| {
for (service.ports) |port| {
var addresses = std.ArrayList([]const u8);
errdefer addresses.deinit();
if (device.primary_ip6) |ip| {
log.info("found service {d} {s} {s} {s} {d}", .{ device.id, name, ip.ip(), service.name, port });
try addresses.append(ip.ip());
}
if (device.primary_ip4) |ip| {
log.info("found service {d} {s} {s} {s} {d}", .{ device.id, name, ip.ip(), service.name, port });
try addresses.append(ip.ip());
}
const config: Config = .{
.name = name,
.type = t: {
var output: [32]u8 = undefined;
std.ascii.lowerString(&output, service.name);
break :t try std.meta.stringToEnum(ConnectionType, std.ascii.lowerString(output, service.name));
},
.comment = c: {
const c = try alloc.dupe(u8, name);
std.mem.replaceScalar(u8, c, '-', ' ');
break :c c;
},
.addresses = addresses.toOwnedSlice(),
.port = port,
.username = try alloc.dupe(u8, "jcollie"),
.manufacturer = try alloc.dupe(u8, device.device_type.manufacturer.name),
.model = try alloc.dupe(u8, device.device_type.model),
.part_number = try alloc.dupe(u8, part_number),
.class = c: {
const c = try alloc.dupe(u8, name);
for (c, 0..) |b, i| {
switch (b) {
'a'...'z' => {},
'A'...'Z' => {},
'0'...'9' => {},
'_' => {},
else => c[i] = '_',
}
}
break :c c;
},
};
{
var buf = std.ArrayList(u8).init(alloc);
try std.json.stringify(config, .{}, buf.writer());
}
}
}
},
.err => |err| {
log.err("error from netbox: {s}", .{err.detail});
},
}
}
}
},
.err => |err| {
log.err("error from netbox: {s}", .{err.detail});
return;
},
}
}
}
// switch (service_result) {
// .ok => |services| {
// for (services.items) |service| {
// for (service.ports) |port| {
// var addresses = std.ArrayList([]const u8);
// errdefer addresses.deinit();
// if (device.primary_ip6) |ip| {
// log.info("found service {d} {s} {s} {s} {d}", .{ device.id, name, ip.ip(), service.name, port });
// try addresses.append(ip.ip());
// }
// if (device.primary_ip4) |ip| {
// log.info("found service {d} {s} {s} {s} {d}", .{ device.id, name, ip.ip(), service.name, port });
// try addresses.append(ip.ip());
// }
// const config: Config = .{
// .name = name,
// .type = t: {
// var output: [32]u8 = undefined;
// std.ascii.lowerString(&output, service.name);
// break :t try std.meta.stringToEnum(ConnectionType, std.ascii.lowerString(output, service.name));
// },
// .comment = c: {
// const c = try alloc.dupe(u8, name);
// std.mem.replaceScalar(u8, c, '-', ' ');
// break :c c;
// },
// .addresses = addresses.toOwnedSlice(),
// .port = port,
// .username = try alloc.dupe(u8, "jcollie"),
// .manufacturer = try alloc.dupe(u8, device.device_type.manufacturer.name),
// .model = try alloc.dupe(u8, device.device_type.model),
// .part_number = try alloc.dupe(u8, part_number),
// .class = c: {
// const c = try alloc.dupe(u8, name);
// for (c, 0..) |b, i| {
// switch (b) {
// 'a'...'z' => {},
// 'A'...'Z' => {},
// '0'...'9' => {},
// '_' => {},
// else => c[i] = '_',
// }
// }
// break :c c;
// },
// };
// {
// var buf = std.ArrayList(u8).init(alloc);
// try std.json.stringify(config, .{}, buf.writer());
// }
// }
// }
// },
// .err => |err| {
// log.err("error from netbox: {s}", .{err.detail});
// },
// }
// }
// }
// },
// .err => |err| {
// log.err("error from netbox: {s}", .{err.detail});
// return;
// },
// }
// }
// }
}