Full Code of pritunl/pritunl-cloud for AI

master e75523642c38 cached
1089 files
7.3 MB
2.0M tokens
6772 symbols
1 requests
Download .txt
Showing preview only (7,830K chars total). Download the full file or copy to clipboard to get everything.
Repository: pritunl/pritunl-cloud
Branch: master
Commit: e75523642c38
Files: 1089
Total size: 7.3 MB

Directory structure:
gitextract_pa6e1wrf/

├── .gitattributes
├── .gitignore
├── CHANGES
├── LICENSE
├── README.md
├── acme/
│   ├── acme.go
│   ├── challenge.go
│   ├── constants.go
│   └── utils.go
├── advisory/
│   ├── advisory.go
│   ├── constants.go
│   └── utils.go
├── agent/
│   ├── agent.go
│   ├── constants/
│   │   └── constants.go
│   ├── imds/
│   │   ├── imds.go
│   │   ├── journal.go
│   │   ├── sync.go
│   │   └── utils.go
│   ├── logging/
│   │   ├── file.go
│   │   ├── handler.go
│   │   ├── logging.go
│   │   └── systemd.go
│   └── utils/
│       ├── sanitize.go
│       └── sys.go
├── aggregate/
│   ├── block.go
│   ├── deployment.go
│   ├── disk.go
│   ├── domain.go
│   ├── instance.go
│   ├── pod.go
│   └── shape.go
├── ahandlers/
│   ├── alert.go
│   ├── audit.go
│   ├── auth.go
│   ├── authority.go
│   ├── balancer.go
│   ├── block.go
│   ├── certificate.go
│   ├── check.go
│   ├── completion.go
│   ├── csrf.go
│   ├── datacenter.go
│   ├── devices.go
│   ├── disk.go
│   ├── domain.go
│   ├── event.go
│   ├── firewall.go
│   ├── handlers.go
│   ├── image.go
│   ├── instance.go
│   ├── license.go
│   ├── log.go
│   ├── node.go
│   ├── organization.go
│   ├── plan.go
│   ├── pod.go
│   ├── policy.go
│   ├── pool.go
│   ├── relations.go
│   ├── secret.go
│   ├── session.go
│   ├── settings.go
│   ├── shape.go
│   ├── static.go
│   ├── storage.go
│   ├── subscription.go
│   ├── theme.go
│   ├── user.go
│   ├── vpc.go
│   └── zone.go
├── alert/
│   ├── alert.go
│   ├── constants.go
│   └── utils.go
├── alertevent/
│   ├── alertevent.go
│   └── utils.go
├── arp/
│   └── arp.go
├── audit/
│   ├── audit.go
│   ├── constants.go
│   └── utils.go
├── auth/
│   ├── auth.go
│   ├── authzero.go
│   ├── azure.go
│   ├── constants.go
│   ├── errortypes.go
│   ├── google.go
│   ├── handler.go
│   ├── jumpcloud.go
│   ├── saml.go
│   ├── state.go
│   ├── sync.go
│   └── utils.go
├── authority/
│   ├── authority.go
│   ├── constants.go
│   └── utils.go
├── authorizer/
│   ├── authorizer.go
│   ├── constants.go
│   └── utils.go
├── backup/
│   └── backup.go
├── balancer/
│   ├── balancer.go
│   ├── constants.go
│   └── utils.go
├── block/
│   ├── block.go
│   ├── constants.go
│   ├── errortypes.go
│   ├── ip.go
│   └── utils.go
├── bridges/
│   └── bridges.go
├── certificate/
│   ├── certificate.go
│   ├── constants.go
│   └── utils.go
├── cloud/
│   ├── cloud.go
│   └── oracle.go
├── cloudinit/
│   ├── cloudinit.go
│   ├── query.go
│   └── utils.go
├── cmd/
│   ├── backup.go
│   ├── dhcp.go
│   ├── imds.go
│   ├── instance.go
│   ├── log.go
│   ├── mtu.go
│   ├── node.go
│   ├── optimize.go
│   └── settings.go
├── colorize/
│   └── colorize.go
├── completion/
│   └── completion.go
├── compositor/
│   └── compositor.go
├── config/
│   └── config.go
├── constants/
│   └── constants.go
├── cookie/
│   ├── cookie.go
│   └── utils.go
├── crypto/
│   └── crypto.go
├── csrf/
│   └── csrf.go
├── data/
│   ├── disk.go
│   ├── image.go
│   ├── resize.go
│   ├── sync.go
│   └── utils.go
├── database/
│   ├── base.go
│   ├── client.go
│   ├── collection.go
│   ├── database.go
│   ├── errors.go
│   ├── index.go
│   └── utils.go
├── datacenter/
│   ├── constants.go
│   ├── datacenter.go
│   └── utils.go
├── defaults/
│   └── defaults.go
├── demo/
│   ├── alert.go
│   ├── authority.go
│   ├── balancer.go
│   ├── block.go
│   ├── certificate.go
│   ├── datacenter.go
│   ├── demo.go
│   ├── disk.go
│   ├── domain.go
│   ├── firewall.go
│   ├── instance.go
│   ├── log.go
│   ├── node.go
│   ├── organization.go
│   ├── plan.go
│   ├── pod.go
│   ├── policy.go
│   ├── pool.go
│   ├── rand.go
│   ├── secret.go
│   ├── shape.go
│   ├── storage.go
│   ├── subscription.go
│   ├── user.go
│   ├── vpc.go
│   └── zone.go
├── deploy/
│   ├── deploy.go
│   ├── deployments.go
│   ├── disks.go
│   ├── imds.go
│   ├── instances.go
│   ├── ipset.go
│   ├── iptables.go
│   ├── namespace.go
│   ├── network.go
│   └── services.go
├── deployment/
│   ├── constants.go
│   ├── deployment.go
│   └── utils.go
├── device/
│   ├── constants.go
│   ├── device.go
│   ├── facet.go
│   └── utils.go
├── dhcpc/
│   ├── constants.go
│   ├── dhcpc.go
│   ├── imds.go
│   ├── lease.go
│   ├── lease4.go
│   ├── lease6.go
│   ├── systemd.go
│   └── utils.go
├── dhcps/
│   ├── dhcp4.go
│   ├── dhcp6.go
│   ├── ndp.go
│   └── systemd.go
├── disk/
│   ├── constants.go
│   ├── disk.go
│   ├── sort.go
│   └── utils.go
├── dns/
│   ├── aws.go
│   ├── cloudflare.go
│   ├── constants.go
│   ├── dns.go
│   ├── errors.go
│   ├── google.go
│   ├── oracle.go
│   └── utils.go
├── dnss/
│   ├── constants.go
│   ├── database.go
│   ├── dnss.go
│   ├── plugin.go
│   └── response.go
├── domain/
│   ├── constants.go
│   ├── domain.go
│   ├── record.go
│   ├── sort.go
│   └── utils.go
├── drive/
│   ├── drive.go
│   └── utils.go
├── engine/
│   ├── bash.go
│   ├── constants.go
│   ├── engine.go
│   ├── parser.go
│   └── python.go
├── errortypes/
│   └── errortypes.go
├── eval/
│   ├── constants.go
│   ├── errortypes.go
│   ├── eval.go
│   └── utils.go
├── event/
│   ├── event.go
│   ├── listener.go
│   └── socket.go
├── features/
│   ├── qemu.go
│   └── systemd.go
├── finder/
│   ├── constants.go
│   └── resources.go
├── firewall/
│   ├── constants.go
│   ├── firewall.go
│   ├── spec.go
│   └── utils.go
├── geo/
│   └── geo.go
├── go.mod
├── go.sum
├── guest/
│   ├── guest.go
│   └── power.go
├── hnetwork/
│   ├── hnetwork.go
│   └── utils.go
├── hugepages/
│   └── hugepages.go
├── image/
│   ├── constants.go
│   ├── errortypes.go
│   ├── image.go
│   ├── sort.go
│   └── utils.go
├── imds/
│   ├── config.go
│   ├── imds.go
│   ├── resource/
│   │   ├── resource.go
│   │   └── utils.go
│   ├── server/
│   │   ├── config/
│   │   │   └── config.go
│   │   ├── constants/
│   │   │   └── constants.go
│   │   ├── errortypes/
│   │   │   └── errortypes.go
│   │   ├── handlers/
│   │   │   ├── certificate.go
│   │   │   ├── dhcp.go
│   │   │   ├── handlers.go
│   │   │   ├── instance.go
│   │   │   ├── node.go
│   │   │   ├── query.go
│   │   │   ├── secret.go
│   │   │   ├── sync.go
│   │   │   └── vpc.go
│   │   ├── router/
│   │   │   └── router.go
│   │   ├── server.go
│   │   ├── state/
│   │   │   └── state.go
│   │   └── utils/
│   │       ├── files.go
│   │       ├── misc.go
│   │       └── request.go
│   ├── systemd.go
│   └── types/
│       ├── certificate.go
│       ├── config.go
│       ├── constants.go
│       ├── domain.go
│       ├── instance.go
│       ├── journal.go
│       ├── node.go
│       ├── pod.go
│       ├── secret.go
│       ├── state.go
│       └── vpc.go
├── info/
│   └── instance.go
├── instance/
│   ├── constants.go
│   ├── errortypes.go
│   ├── instance.go
│   └── utils.go
├── interfaces/
│   └── interfaces.go
├── ip/
│   ├── interface.go
│   └── ip.go
├── iproute/
│   ├── address.go
│   ├── bridge.go
│   └── iface.go
├── ipset/
│   ├── names.go
│   ├── sets.go
│   ├── state.go
│   └── utils.go
├── iptables/
│   ├── iptables.go
│   ├── lock.go
│   ├── rules.go
│   ├── state.go
│   ├── update.go
│   └── utils.go
├── ipvs/
│   ├── constants.go
│   ├── ipvs.go
│   ├── service.go
│   └── target.go
├── iscsi/
│   └── iscsi.go
├── iso/
│   └── iso.go
├── journal/
│   ├── constants.go
│   ├── journal.go
│   ├── store.go
│   └── utils.go
├── lock/
│   └── lvm.go
├── log/
│   ├── constants.go
│   ├── log.go
│   └── utils.go
├── logger/
│   ├── database.go
│   ├── file.go
│   ├── formatter.go
│   ├── hook.go
│   ├── limiter.go
│   ├── logger.go
│   ├── sender.go
│   └── writer.go
├── lvm/
│   ├── lv.go
│   └── vgs.go
├── main.go
├── middlewear/
│   ├── gzip.go
│   └── middlewear.go
├── mtu/
│   └── mtu.go
├── netconf/
│   ├── address.go
│   ├── base.go
│   ├── bridge.go
│   ├── clear.go
│   ├── external.go
│   ├── host.go
│   ├── iface.go
│   ├── imds.go
│   ├── internal.go
│   ├── ip.go
│   ├── netconf.go
│   ├── nodeport.go
│   ├── oracle.go
│   ├── space.go
│   ├── utils.go
│   ├── validate.go
│   └── vlan.go
├── node/
│   ├── block.go
│   ├── certificate.go
│   ├── constants.go
│   ├── interfaces.go
│   ├── node.go
│   ├── oracle.go
│   └── utils.go
├── nodeport/
│   ├── constants.go
│   ├── mapping.go
│   ├── network.go
│   ├── nodeport.go
│   └── utils.go
├── nonce/
│   └── nonce.go
├── notification/
│   └── notification.go
├── oracle/
│   ├── iface.go
│   ├── metadata.go
│   ├── oracle.go
│   ├── provider.go
│   ├── routetable.go
│   ├── subnet.go
│   ├── utils.go
│   └── vnic.go
├── organization/
│   ├── organization.go
│   └── utils.go
├── paths/
│   ├── paths.go
│   └── utils.go
├── pci/
│   ├── pci.go
│   └── utils.go
├── permission/
│   ├── permission.go
│   └── user.go
├── plan/
│   ├── constants.go
│   ├── data.go
│   ├── plan.go
│   └── utils.go
├── planner/
│   ├── planner.go
│   └── utils.go
├── pod/
│   ├── pod.go
│   └── utils.go
├── policy/
│   ├── constants.go
│   ├── policy.go
│   └── utils.go
├── pool/
│   ├── constants.go
│   ├── pool.go
│   └── utils.go
├── proxy/
│   ├── constants.go
│   ├── domain.go
│   ├── errortypes.go
│   ├── proxy.go
│   ├── resolver.go
│   ├── reverse.go
│   ├── transport.go
│   ├── types.go
│   ├── utils.go
│   └── ws.go
├── qemu/
│   ├── constants.go
│   ├── data.go
│   ├── disk.go
│   ├── manage.go
│   ├── network.go
│   ├── power.go
│   ├── qemu.go
│   ├── routes.go
│   ├── sort.go
│   ├── usb.go
│   └── utils.go
├── qga/
│   └── qga.go
├── qmp/
│   ├── backup.go
│   ├── disk.go
│   ├── errors.go
│   ├── password.go
│   ├── power.go
│   ├── qmp.go
│   └── vnc.go
├── qms/
│   ├── disk.go
│   ├── power.go
│   ├── qms.go
│   ├── usb.go
│   ├── utils.go
│   └── vnc.go
├── redirect/
│   ├── acme.go
│   ├── crypto/
│   │   └── crypto.go
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
│   └── utils.go
├── relations/
│   ├── definitions/
│   │   ├── block.go
│   │   ├── certificate.go
│   │   ├── datacenter.go
│   │   ├── definitions.go
│   │   ├── firewall.go
│   │   ├── instance.go
│   │   ├── node.go
│   │   ├── organization.go
│   │   ├── pod.go
│   │   ├── policy.go
│   │   ├── secret.go
│   │   ├── shape.go
│   │   ├── vpc.go
│   │   └── zone.go
│   ├── registry.go
│   ├── relations.go
│   ├── response.go
│   └── utils.go
├── render/
│   ├── constants.go
│   └── render.go
├── requires/
│   ├── errors.go
│   └── requires.go
├── rokey/
│   ├── cache.go
│   ├── rokey.go
│   └── utils.go
├── router/
│   ├── certificates.go
│   ├── constants.go
│   └── router.go
├── scheduler/
│   ├── constants.go
│   ├── scheduler.go
│   ├── unit.go
│   └── utils.go
├── secondary/
│   ├── constants.go
│   ├── duo.go
│   ├── errors.go
│   ├── okta.go
│   ├── onelogin.go
│   ├── secondary.go
│   └── utils.go
├── secret/
│   ├── constants.go
│   ├── oracle.go
│   ├── secret.go
│   └── utils.go
├── session/
│   ├── constants.go
│   ├── session.go
│   └── utils.go
├── settings/
│   ├── acme.go
│   ├── auth.go
│   ├── hypervisor.go
│   ├── local.go
│   ├── registry.go
│   ├── router.go
│   ├── settings.go
│   ├── system.go
│   └── telemetry.go
├── setup/
│   └── iptables.go
├── shape/
│   ├── constants.go
│   ├── node.go
│   ├── shape.go
│   └── utils.go
├── signature/
│   ├── signature.go
│   └── utils.go
├── spec/
│   ├── constants.go
│   ├── domain.go
│   ├── firewall.go
│   ├── instance.go
│   ├── journal.go
│   ├── node.go
│   ├── spec.go
│   └── utils.go
├── state/
│   ├── arps.go
│   ├── authorities.go
│   ├── authorities_preload.go
│   ├── datacenter.go
│   ├── deployments.go
│   ├── disks.go
│   ├── domains.go
│   ├── firewalls.go
│   ├── firewalls_preload.go
│   ├── instances.go
│   ├── instances_preload.go
│   ├── network.go
│   ├── package.go
│   ├── pools.go
│   ├── runtimes.go
│   ├── schedulers.go
│   ├── state.go
│   ├── state_old.go
│   ├── virtuals.go
│   ├── vpcs.go
│   ├── zone.go
│   └── zones.go
├── static/
│   ├── file.go
│   └── static.go
├── storage/
│   ├── constants.go
│   ├── storage.go
│   └── utils.go
├── store/
│   ├── address.go
│   ├── arp.go
│   ├── disks.go
│   ├── routes.go
│   ├── usb.go
│   └── virt.go
├── subscription/
│   └── subscription.go
├── sync/
│   ├── auth.go
│   ├── nodes.go
│   ├── sync.go
│   └── vm.go
├── systemd/
│   ├── systemd.go
│   └── utils.go
├── task/
│   ├── acme.go
│   ├── advisory.go
│   ├── backing.go
│   ├── balancer.go
│   ├── blocks.go
│   ├── cache.go
│   ├── constants.go
│   ├── deployments.go
│   ├── domains.go
│   ├── imds.go
│   ├── job.go
│   ├── notification.go
│   ├── scheduler.go
│   ├── spec.go
│   ├── specindex.go
│   ├── storage.go
│   └── task.go
├── telemetry/
│   ├── constants.go
│   ├── telemetry.go
│   ├── updates.go
│   └── utils.go
├── tools/
│   ├── autoindex.py
│   ├── build_run.sh
│   ├── builder.py
│   ├── generate_demo_data.py
│   ├── generate_files.py
│   ├── package/
│   │   ├── PKGBUILD
│   │   └── README.md
│   ├── pritunl-cloud-redirect.service
│   ├── pritunl-cloud-redirect.socket
│   ├── pritunl-cloud.service
│   ├── tsc_run.sh
│   ├── virt-install/
│   │   ├── README.md
│   │   ├── download.sh
│   │   ├── install/
│   │   │   ├── almalinux10.sh
│   │   │   ├── almalinux8.sh
│   │   │   ├── almalinux9.sh
│   │   │   ├── alpinelinux.sh
│   │   │   ├── archlinux.sh
│   │   │   ├── fedora43.sh
│   │   │   ├── fedora44.sh
│   │   │   ├── freebsd.sh
│   │   │   ├── oraclelinux10.sh
│   │   │   ├── oraclelinux7.sh
│   │   │   ├── oraclelinux8.sh
│   │   │   ├── oraclelinux9.sh
│   │   │   ├── rockylinux10.sh
│   │   │   ├── rockylinux8.sh
│   │   │   ├── rockylinux9.sh
│   │   │   ├── ubuntu24.sh
│   │   │   └── ubuntu26.sh
│   │   └── setup/
│   │       ├── alpine.sh
│   │       ├── arch.sh
│   │       ├── debian.sh
│   │       ├── fedora.sh
│   │       ├── freebsd.sh
│   │       ├── rhel10.sh
│   │       ├── rhel7.sh
│   │       ├── rhel8.sh
│   │       └── rhel9.sh
│   └── webpack_run.sh
├── tpm/
│   ├── tpm.go
│   └── utils.go
├── twilio/
│   ├── twilio.go
│   └── utils.go
├── uhandlers/
│   ├── alert.go
│   ├── auth.go
│   ├── authority.go
│   ├── balancer.go
│   ├── certificate.go
│   ├── check.go
│   ├── completion.go
│   ├── csrf.go
│   ├── datacenter.go
│   ├── devices.go
│   ├── disk.go
│   ├── domain.go
│   ├── event.go
│   ├── firewall.go
│   ├── handlers.go
│   ├── image.go
│   ├── instance.go
│   ├── license.go
│   ├── node.go
│   ├── organization.go
│   ├── plan.go
│   ├── pod.go
│   ├── pool.go
│   ├── relations.go
│   ├── secret.go
│   ├── shape.go
│   ├── static.go
│   ├── theme.go
│   ├── utils.go
│   ├── vpc.go
│   └── zone.go
├── unit/
│   ├── unit.go
│   └── utils.go
├── upgrade/
│   ├── created.go
│   ├── instance.go
│   ├── journal.go
│   ├── node.go
│   ├── objectid.go
│   ├── roles.go
│   ├── state.go
│   ├── upgrade.go
│   └── zone_datacenter.go
├── usb/
│   ├── usb.go
│   └── utils.go
├── user/
│   ├── constants.go
│   ├── user.go
│   └── utils.go
├── useragent/
│   └── useragent.go
├── utils/
│   ├── crypto.go
│   ├── dns.go
│   ├── files.go
│   ├── filter.go
│   ├── limiter.go
│   ├── math.go
│   ├── misc.go
│   ├── multilock.go
│   ├── multitimeoutlock.go
│   ├── network.go
│   ├── proc.go
│   ├── prompt.go
│   ├── psutil_freebsd.go
│   ├── psutil_linux.go
│   ├── randomname.go
│   ├── request.go
│   ├── sort.go
│   ├── timeoutlock.go
│   ├── unix.go
│   └── webauthn.go
├── validator/
│   └── validator.go
├── version/
│   ├── cache.go
│   ├── utils.go
│   └── version.go
├── virtiofs/
│   ├── systemd.go
│   ├── utils.go
│   └── virtiofs.go
├── vm/
│   ├── constants.go
│   ├── sort.go
│   ├── utils.go
│   └── vm.go
├── vmdk/
│   └── utils.go
├── vpc/
│   ├── constants.go
│   ├── ip.go
│   ├── subnet.go
│   ├── utils.go
│   └── vpc.go
├── vxlan/
│   └── vxlan.go
├── www/
│   ├── .gitignore
│   ├── README.md
│   ├── app/
│   │   ├── Alert.ts
│   │   ├── App.tsx
│   │   ├── Constants.ts
│   │   ├── Csrf.ts
│   │   ├── EditorThemes.ts
│   │   ├── Event.ts
│   │   ├── EventEmitter.ts
│   │   ├── License.ts
│   │   ├── Loader.ts
│   │   ├── References.d.ts
│   │   ├── Router.ts
│   │   ├── Styles.tsx
│   │   ├── Theme.ts
│   │   ├── actions/
│   │   │   ├── AlertActions.ts
│   │   │   ├── AuditActions.ts
│   │   │   ├── AuthorityActions.ts
│   │   │   ├── BalancerActions.ts
│   │   │   ├── BlockActions.ts
│   │   │   ├── CertificateActions.ts
│   │   │   ├── CompletionActions.ts
│   │   │   ├── DatacenterActions.ts
│   │   │   ├── DeviceActions.ts
│   │   │   ├── DiskActions.ts
│   │   │   ├── DomainActions.ts
│   │   │   ├── FirewallActions.ts
│   │   │   ├── ImageActions.ts
│   │   │   ├── InstanceActions.ts
│   │   │   ├── LogActions.ts
│   │   │   ├── NodeActions.ts
│   │   │   ├── OrganizationActions.ts
│   │   │   ├── PlanActions.ts
│   │   │   ├── PodActions.ts
│   │   │   ├── PolicyActions.ts
│   │   │   ├── PoolActions.ts
│   │   │   ├── RelationsActions.ts
│   │   │   ├── SecretActions.ts
│   │   │   ├── SessionActions.ts
│   │   │   ├── SettingsActions.ts
│   │   │   ├── ShapeActions.ts
│   │   │   ├── StorageActions.ts
│   │   │   ├── SubscriptionActions.ts
│   │   │   ├── UserActions.ts
│   │   │   ├── VpcActions.ts
│   │   │   └── ZoneActions.ts
│   │   ├── completion/
│   │   │   ├── Cache.ts
│   │   │   ├── Engine.ts
│   │   │   └── Types.ts
│   │   ├── components/
│   │   │   ├── AdvisoryDialog.tsx
│   │   │   ├── Alert.tsx
│   │   │   ├── AlertDetailed.tsx
│   │   │   ├── AlertNew.tsx
│   │   │   ├── Alerts.tsx
│   │   │   ├── AlertsFilter.tsx
│   │   │   ├── AlertsPage.tsx
│   │   │   ├── Audit.tsx
│   │   │   ├── Audits.tsx
│   │   │   ├── AuditsPage.tsx
│   │   │   ├── Authorities.tsx
│   │   │   ├── AuthoritiesFilter.tsx
│   │   │   ├── AuthoritiesPage.tsx
│   │   │   ├── Authority.tsx
│   │   │   ├── AuthorityDetailed.tsx
│   │   │   ├── AuthorityNew.tsx
│   │   │   ├── Balancer.tsx
│   │   │   ├── BalancerBackend.tsx
│   │   │   ├── BalancerDetailed.tsx
│   │   │   ├── BalancerDomain.tsx
│   │   │   ├── BalancerNew.tsx
│   │   │   ├── Balancers.tsx
│   │   │   ├── BalancersFilter.tsx
│   │   │   ├── BalancersPage.tsx
│   │   │   ├── Block.tsx
│   │   │   ├── BlockDetailed.tsx
│   │   │   ├── BlockNew.tsx
│   │   │   ├── Blocks.tsx
│   │   │   ├── BlocksFilter.tsx
│   │   │   ├── BlocksPage.tsx
│   │   │   ├── Certificate.tsx
│   │   │   ├── CertificateDetailed.tsx
│   │   │   ├── CertificateDomain.tsx
│   │   │   ├── CertificateNew.tsx
│   │   │   ├── Certificates.tsx
│   │   │   ├── CertificatesFilter.tsx
│   │   │   ├── CertificatesPage.tsx
│   │   │   ├── ConfirmButton.tsx
│   │   │   ├── CopyButton.tsx
│   │   │   ├── Datacenter.tsx
│   │   │   ├── DatacenterDetailed.tsx
│   │   │   ├── DatacenterNew.tsx
│   │   │   ├── Datacenters.tsx
│   │   │   ├── DatacentersFilter.tsx
│   │   │   ├── DatacentersPage.tsx
│   │   │   ├── Device.tsx
│   │   │   ├── Devices.tsx
│   │   │   ├── Disk.tsx
│   │   │   ├── DiskDetailed.tsx
│   │   │   ├── DiskNew.tsx
│   │   │   ├── Disks.tsx
│   │   │   ├── DisksFilter.tsx
│   │   │   ├── DisksPage.tsx
│   │   │   ├── Domain.tsx
│   │   │   ├── DomainDetailed.tsx
│   │   │   ├── DomainNew.tsx
│   │   │   ├── DomainRecord.tsx
│   │   │   ├── Domains.tsx
│   │   │   ├── DomainsFilter.tsx
│   │   │   ├── DomainsPage.tsx
│   │   │   ├── Editor.tsx
│   │   │   ├── Firewall.tsx
│   │   │   ├── FirewallDetailed.tsx
│   │   │   ├── FirewallNew.tsx
│   │   │   ├── FirewallRule.tsx
│   │   │   ├── Firewalls.tsx
│   │   │   ├── FirewallsFilter.tsx
│   │   │   ├── FirewallsPage.tsx
│   │   │   ├── Help.tsx
│   │   │   ├── Image.tsx
│   │   │   ├── ImageDetailed.tsx
│   │   │   ├── Images.tsx
│   │   │   ├── ImagesFilter.tsx
│   │   │   ├── ImagesPage.tsx
│   │   │   ├── Instance.tsx
│   │   │   ├── InstanceDetailed.tsx
│   │   │   ├── InstanceImages.tsx
│   │   │   ├── InstanceIscsiDevice.tsx
│   │   │   ├── InstanceLicense.tsx
│   │   │   ├── InstanceMount.tsx
│   │   │   ├── InstanceNew.tsx
│   │   │   ├── InstanceNodePort.tsx
│   │   │   ├── Instances.tsx
│   │   │   ├── InstancesFilter.tsx
│   │   │   ├── InstancesPage.tsx
│   │   │   ├── LoadingBar.tsx
│   │   │   ├── LoadingCircle.tsx
│   │   │   ├── Log.tsx
│   │   │   ├── LogViewer.tsx
│   │   │   ├── Logs.tsx
│   │   │   ├── LogsFilter.tsx
│   │   │   ├── LogsPage.tsx
│   │   │   ├── Main.tsx
│   │   │   ├── MarkdownMemo.tsx
│   │   │   ├── Node.tsx
│   │   │   ├── NodeBlock.tsx
│   │   │   ├── NodeDeploy.tsx
│   │   │   ├── NodeDetailed.tsx
│   │   │   ├── NodeShare.tsx
│   │   │   ├── Nodes.tsx
│   │   │   ├── NodesFilter.tsx
│   │   │   ├── NodesPage.tsx
│   │   │   ├── NonState.tsx
│   │   │   ├── Organization.tsx
│   │   │   ├── OrganizationDetailed.tsx
│   │   │   ├── OrganizationNew.tsx
│   │   │   ├── OrganizationSelect.tsx
│   │   │   ├── Organizations.tsx
│   │   │   ├── OrganizationsFilter.tsx
│   │   │   ├── OrganizationsPage.tsx
│   │   │   ├── Page.tsx
│   │   │   ├── PageButton.tsx
│   │   │   ├── PageCreate.tsx
│   │   │   ├── PageCustom.tsx
│   │   │   ├── PageDateTime.tsx
│   │   │   ├── PageHeader.tsx
│   │   │   ├── PageInfo.tsx
│   │   │   ├── PageInput.tsx
│   │   │   ├── PageInputButton.tsx
│   │   │   ├── PageInputSwitch.tsx
│   │   │   ├── PageNew.tsx
│   │   │   ├── PageNumInput.tsx
│   │   │   ├── PagePanel.tsx
│   │   │   ├── PageSave.tsx
│   │   │   ├── PageSelect.tsx
│   │   │   ├── PageSelectButton.tsx
│   │   │   ├── PageSelectButtonConfirm.tsx
│   │   │   ├── PageSelector.tsx
│   │   │   ├── PageSplit.tsx
│   │   │   ├── PageSwitch.tsx
│   │   │   ├── PageTextArea.tsx
│   │   │   ├── Plan.tsx
│   │   │   ├── PlanDetailed.tsx
│   │   │   ├── PlanEditor.tsx
│   │   │   ├── PlanNew.tsx
│   │   │   ├── PlanStatement.tsx
│   │   │   ├── Plans.tsx
│   │   │   ├── PlansFilter.tsx
│   │   │   ├── PlansPage.tsx
│   │   │   ├── Pod.tsx
│   │   │   ├── PodDeploy.tsx
│   │   │   ├── PodDeployment.tsx
│   │   │   ├── PodDeploymentEdit.tsx
│   │   │   ├── PodDetailed.tsx
│   │   │   ├── PodEditor.tsx
│   │   │   ├── PodMigrate.tsx
│   │   │   ├── PodNew.tsx
│   │   │   ├── PodUnit.tsx
│   │   │   ├── PodWorkspace.tsx
│   │   │   ├── Pods.tsx
│   │   │   ├── PodsFilter.tsx
│   │   │   ├── PodsPage.tsx
│   │   │   ├── Policies.tsx
│   │   │   ├── PoliciesFilter.tsx
│   │   │   ├── PoliciesPage.tsx
│   │   │   ├── Policy.tsx
│   │   │   ├── PolicyDetailed.tsx
│   │   │   ├── PolicyNew.tsx
│   │   │   ├── PolicyRule.tsx
│   │   │   ├── Pool.tsx
│   │   │   ├── PoolDetailed.tsx
│   │   │   ├── PoolNew.tsx
│   │   │   ├── Pools.tsx
│   │   │   ├── PoolsFilter.tsx
│   │   │   ├── PoolsPage.tsx
│   │   │   ├── Relations.tsx
│   │   │   ├── RouterLink.tsx
│   │   │   ├── RouterRedirect.tsx
│   │   │   ├── RouterRoute.tsx
│   │   │   ├── RouterRoutes.tsx
│   │   │   ├── SearchInput.tsx
│   │   │   ├── Secret.tsx
│   │   │   ├── SecretDetailed.tsx
│   │   │   ├── SecretNew.tsx
│   │   │   ├── Secrets.tsx
│   │   │   ├── SecretsFilter.tsx
│   │   │   ├── SecretsPage.tsx
│   │   │   ├── Session.tsx
│   │   │   ├── Sessions.tsx
│   │   │   ├── Settings.tsx
│   │   │   ├── SettingsProvider.tsx
│   │   │   ├── SettingsSecondaryProvider.tsx
│   │   │   ├── Shape.tsx
│   │   │   ├── ShapeDetailed.tsx
│   │   │   ├── ShapeNew.tsx
│   │   │   ├── Shapes.tsx
│   │   │   ├── ShapesFilter.tsx
│   │   │   ├── ShapesPage.tsx
│   │   │   ├── Storage.tsx
│   │   │   ├── StorageDetailed.tsx
│   │   │   ├── StorageNew.tsx
│   │   │   ├── Storages.tsx
│   │   │   ├── StoragesFilter.tsx
│   │   │   ├── StoragesPage.tsx
│   │   │   ├── Subscription.tsx
│   │   │   ├── Switch.tsx
│   │   │   ├── SwitchNull.tsx
│   │   │   ├── User.tsx
│   │   │   ├── UserDetailed.tsx
│   │   │   ├── Users.tsx
│   │   │   ├── UsersFilter.tsx
│   │   │   ├── UsersPage.tsx
│   │   │   ├── Vpc.tsx
│   │   │   ├── VpcArp.tsx
│   │   │   ├── VpcDetailed.tsx
│   │   │   ├── VpcLinkUri.tsx
│   │   │   ├── VpcMap.tsx
│   │   │   ├── VpcNew.tsx
│   │   │   ├── VpcRoute.tsx
│   │   │   ├── VpcSubnet.tsx
│   │   │   ├── Vpcs.tsx
│   │   │   ├── VpcsFilter.tsx
│   │   │   ├── VpcsPage.tsx
│   │   │   ├── Zone.tsx
│   │   │   ├── ZoneDetailed.tsx
│   │   │   ├── ZoneNew.tsx
│   │   │   ├── Zones.tsx
│   │   │   ├── ZonesFilter.tsx
│   │   │   └── ZonesPage.tsx
│   │   ├── dispatcher/
│   │   │   ├── Base.ts
│   │   │   ├── Dispatcher.ts
│   │   │   ├── EventDispatcher.ts
│   │   │   └── LoadingDispatcher.ts
│   │   ├── stores/
│   │   │   ├── AlertsStore.ts
│   │   │   ├── AuditsStore.ts
│   │   │   ├── AuthoritiesStore.ts
│   │   │   ├── BalancersStore.ts
│   │   │   ├── BlocksStore.ts
│   │   │   ├── CertificatesStore.ts
│   │   │   ├── CompletionStore.ts
│   │   │   ├── DatacentersStore.ts
│   │   │   ├── DevicesStore.ts
│   │   │   ├── DisksStore.ts
│   │   │   ├── DomainsNameStore.ts
│   │   │   ├── DomainsStore.ts
│   │   │   ├── FirewallsStore.ts
│   │   │   ├── ImagesDatacenterStore.ts
│   │   │   ├── ImagesStore.ts
│   │   │   ├── InstancesNodeStore.ts
│   │   │   ├── InstancesStore.ts
│   │   │   ├── LoadingStore.ts
│   │   │   ├── LogsStore.ts
│   │   │   ├── NodesStore.ts
│   │   │   ├── NodesZoneStore.ts
│   │   │   ├── OrganizationsStore.ts
│   │   │   ├── PlansStore.ts
│   │   │   ├── PodsStore.ts
│   │   │   ├── PodsUnitStore.ts
│   │   │   ├── PoliciesStore.ts
│   │   │   ├── PoolsStore.ts
│   │   │   ├── SecretsStore.ts
│   │   │   ├── SessionsStore.ts
│   │   │   ├── SettingsStore.ts
│   │   │   ├── ShapesStore.ts
│   │   │   ├── StoragesStore.ts
│   │   │   ├── SubscriptionStore.ts
│   │   │   ├── UserStore.ts
│   │   │   ├── UsersStore.ts
│   │   │   ├── VpcsNameStore.ts
│   │   │   ├── VpcsStore.ts
│   │   │   └── ZonesStore.ts
│   │   ├── types/
│   │   │   ├── AgentTypes.ts
│   │   │   ├── AlertTypes.ts
│   │   │   ├── AuditTypes.ts
│   │   │   ├── AuthorityTypes.ts
│   │   │   ├── BalancerTypes.ts
│   │   │   ├── BlockTypes.ts
│   │   │   ├── CertificateTypes.ts
│   │   │   ├── CompletionTypes.ts
│   │   │   ├── DatacenterTypes.ts
│   │   │   ├── DeviceTypes.ts
│   │   │   ├── DiskTypes.ts
│   │   │   ├── DomainTypes.ts
│   │   │   ├── FirewallTypes.ts
│   │   │   ├── GlobalTypes.ts
│   │   │   ├── ImageTypes.ts
│   │   │   ├── InstanceTypes.ts
│   │   │   ├── LoadingTypes.ts
│   │   │   ├── LogTypes.ts
│   │   │   ├── NodeTypes.ts
│   │   │   ├── OrganizationTypes.ts
│   │   │   ├── PlanTypes.ts
│   │   │   ├── PodTypes.ts
│   │   │   ├── PolicyTypes.ts
│   │   │   ├── PoolTypes.ts
│   │   │   ├── RelationTypes.ts
│   │   │   ├── RouterTypes.ts
│   │   │   ├── SecretTypes.ts
│   │   │   ├── SessionTypes.ts
│   │   │   ├── SettingsTypes.ts
│   │   │   ├── ShapeTypes.ts
│   │   │   ├── StorageTypes.ts
│   │   │   ├── SubscriptionTypes.ts
│   │   │   ├── UserTypes.ts
│   │   │   ├── VpcTypes.ts
│   │   │   └── ZoneTypes.ts
│   │   └── utils/
│   │       ├── AgentUtils.ts
│   │       └── MiscUtils.tsx
│   ├── build.sh
│   ├── build_remote.sh
│   ├── dist/
│   │   ├── index.html
│   │   ├── login.html
│   │   ├── static/
│   │   │   ├── blueprint-datetime2.css
│   │   │   ├── blueprint-icons.css
│   │   │   ├── blueprint3.css
│   │   │   ├── blueprint5.css
│   │   │   ├── global.css
│   │   │   └── normalize.css
│   │   └── uindex.html
│   ├── dist-dev/
│   │   ├── index.html
│   │   ├── login.html
│   │   ├── static/
│   │   │   ├── blueprint-datetime2.css
│   │   │   ├── blueprint-icons.css
│   │   │   ├── blueprint3.css
│   │   │   ├── blueprint5.css
│   │   │   ├── global.css
│   │   │   └── normalize.css
│   │   └── uindex.html
│   ├── index.html
│   ├── index_dist.html
│   ├── login.html
│   ├── package.json
│   ├── styles/
│   │   ├── blueprint.css
│   │   └── global.css
│   ├── tsconfig.json
│   ├── uindex.html
│   ├── uindex_dist.html
│   ├── webpack.config.js
│   └── webpack.dev.config.js
└── zone/
    ├── constants.go
    ├── utils.go
    └── zone.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
www/app/EditorThemes.ts linguist-vendored
*.html linguist-vendored
*.css linguist-vendored
*.js linguist-vendored


================================================
FILE: .gitignore
================================================
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
*.pyc
*.egg
*.egg-info
build_keys.json
/pritunl-cloud
/builder/builder
/agent/agent
/imds/server/server


================================================
FILE: CHANGES
================================================
pritunl-cloud changelog
=======================

<%= version %>

Add Google Cloud DNS support
Add support to manual renew certificates
Fix host network bridge management issues
Optimize database indexes

Version 2.0.3665.99 2025-12-06
------------------------------

Add internal DNS system
Add arch linux support
Improve Route53 DNS management
Improve instance layout in web console
Improve instance web console VNC

Version 2.0.3616.97 2025-10-18
------------------------------

Add journal kind to pods
Add support for QEMU 10
Improve QEMU tuning
Fix relations query
Fix RHEL 7 IPv6 network configuration
Add imds service recovery
Add update advisories
Web console layout improvements

Version 2.0.3592.49 2025-09-24
------------------------------

Add pod system
Add imds service
Add secrets storage
Add LVM storage pools
Add DNS TXT verification for Lets Encrypt
Add support for custom vpc arp entries
Add node port support
Add dhcp client and server
Add cloud script support

Version 1.2.2933.86 2023-12-05
------------------------------

Fix fast login issues

Version 1.2.2900.76 2023-11-02
------------------------------

Improve single sign-on fast login

Version 1.2.2853.96 2023-09-16
------------------------------

Add VPC network maps
Fix QEMU desktop GUI on Fedora 38

Version 1.2.2759.95 2023-06-14
------------------------------

Add support for Fedora 38
Add fast login

Version 1.2.2653.26 2023-02-28
------------------------------

Improve instance backup support

Version 1.2.2626.74 2023-02-01
------------------------------

Fix kernel compatibility issue

Version 1.2.2626.25 2023-02-01
------------------------------

Support RHEL 9
Web interface design changes
Fix network configuration issue with IPv6 instances

Version 1.2.2415.36 2022-07-05
------------------------------

Update cloud init configuration

Version 1.2.2415.30 2022-07-05
------------------------------

Update QEMU configuration

Version 1.2.2414.59 2022-07-04
------------------------------

Add FreeBSD support
Add Windows 11 support
Add instance TPM support
Add instance DHCP server
Configure node firewall in node init

Version 1.2.2400.46 2022-06-20
------------------------------

Fix QEMU feature detection

Version 1.2.2400.30 2022-06-20
------------------------------

Add AlmaLinux image labels

Version 1.2.2399.48 2022-06-19
------------------------------

Show running QEMU version in instance info
Improve Lets Encrypt certificates

Version 1.2.2397.83 2022-06-17
------------------------------

Support QEMU 7.0.0
Support Azure users with more then 50 groups

Version 1.2.2336.5 2022-04-17
-----------------------------

Fix compatibility issue with Fedora update

Version 1.2.2335.81 2022-04-16
------------------------------

Add support for MongoDB unix socket

Version 1.2.2334.82 2022-04-15
------------------------------

Support IPv6 only instances

Version 1.2.2334.69 2022-04-15
------------------------------

Fix issue with instance startup

Version 1.2.2333.97 2022-04-14
------------------------------

Improve instance management

Version 1.2.2333.91 2022-04-14
------------------------------

Improve instance IPv6 networking

Version 1.2.2333.80 2022-04-14
------------------------------

Improve instance networking

Version 1.2.2330.66 2022-04-11
------------------------------

Add option to disable public IPv6 address

Version 1.2.2330.2 2022-04-11
-----------------------------

Improve node init support
Improve instance isolation

Version 1.2.2324.79 2022-04-05
------------------------------

Improve IPv6 networking

Version 1.2.2324.56 2022-04-05
------------------------------

Improve node init support
Add mtu check command
Fix static IPv6 issues

Version 1.2.2301.94 2022-03-13
------------------------------

Add support for internal only jumbo frames
Update image labels for Ubuntu

Version 1.2.2289.56 2022-03-01
------------------------------

Improve node init support

Version 1.2.2287.69 2022-02-27
------------------------------

Improve host networking

Version 1.2.2286.62 2022-02-26
------------------------------

Fix issues with static IPv6 configuration

Version 1.2.2262.39 2022-02-02
------------------------------

Fix U2F migration to WebAuthn issues

Version 1.2.2261.49 2022-02-01
------------------------------

Web interface improvements

Version 1.2.2261.45 2022-02-01
------------------------------

Improve Oracle Cloud networking

Version 1.2.2260.40 2022-01-31
------------------------------

Add hugepages support
Add support for Azure graph API
Add instance gui
Add instance spice server
Add instance source destination check
Add JumpCloud single sign-on
Add instance root password option
Improve instance sandboxing

Version 1.2.2184.82 2021-11-16
------------------------------

Add Oracle Cloud vnic support
Improve qemu support

Version 1.2.2144.31 2021-10-07
------------------------------

Web interface improvements

Version 1.2.2141.15 2021-10-04
------------------------------

Fix zone defaults

Version 1.2.2140.92 2021-10-03
------------------------------

Support instance networking without bridge

Version 1.2.2091.92 2021-08-15
------------------------------

Improve instance networking

Version 1.2.2011.58 2021-05-27
------------------------------

Add uefi instance support
Add secure boot instance support
Add pci passthrough
Add disk resizing
Add disk passthrough
Add iscsi instance disk support
Add instance iso support
Support add and remove USB devices on running instance
Support add and remove disks on running instance
Support wildcard certificates
Format username capitalization on update
Move instance runtime files to run directory
Web interface improvements

Version 1.2.1807.79 2020-11-04
------------------------------

Improve online disk backup
Add VNC client to web console
Add local backup command
Web interface improvements

Version 1.2.1772.58 2020-09-30
------------------------------

Fix issue with multiple instance disks
Fix startup issue

Version 1.0.1743.55 2020-09-01
------------------------------

Web server improvements

Version 1.0.1623.75 2020-05-04
------------------------------

Add web socket support to load balancers

Version 1.2.1595.50 2020-04-06
------------------------------

Add support for network alias interfaces

Version 1.2.1594.77 2020-04-05
------------------------------

Improve node management

Version 1.2.1594.70 2020-04-05
------------------------------

Networking improvements

Version 1.2.1589.78 2020-03-31
------------------------------

Add VPC subnets
Move default data directory
Support IPv6 static blocks
Interface improvements
Add load balancers

Version 1.0.1452.55 2019-11-15
------------------------------

Improve acme v2 support

Version 1.0.1448.49 2019-11-11
------------------------------

Support acme v2
Instance networking improvements
Web interface improvements

Version 1.0.1413.18 2019-10-07
------------------------------

Add support for USB passthrough

Version 1.0.1338.74 2019-07-24
------------------------------

Improve instance management

Version 1.0.1337.5 2019-07-23
-----------------------------

Improve instance management
Add uptime to instance info
Generate random default password

Version 1.0.1213.83 2019-03-21
------------------------------

Web interface improvements

Version 1.0.1213.82 2019-03-21
------------------------------

Add option to disable instance public and host address

Version 1.0.1206.81 2019-03-14
------------------------------

Add VGA option to node settings

Version 1.0.1200.31 2019-03-08
------------------------------

Improve network performance

Version 1.0.1200.25 2019-03-08
------------------------------

Improve instance management

Version 1.0.1199.30 2019-03-07
------------------------------

Fix instance creation issue

Version 1.0.1199.28 2019-03-07
------------------------------

Add instance vnc support

Version 1.0.1197.13 2019-03-05
------------------------------

Set instance hostname

Version 1.0.1189.79 2019-02-25
------------------------------

Improve U2F support
Web interface improvements

Version 1.0.1181.24 2019-02-17
------------------------------

Add redirect server option to node settings

Version 1.0.1180.14 2019-02-16
------------------------------

Add support for Oracle Cloud

Version 1.0.1179.24 2019-02-15
------------------------------

Add host networking

Version 1.0.1173.24 2019-02-09
------------------------------

Add VXLan support

Version 1.0.1169.1 2019-02-05
-----------------------------

Fix node configuration

Version 1.0.1168.95 2019-02-04
------------------------------

Improve node management

Version 1.0.1168.94 2019-02-04
------------------------------

Improve node management

Version 1.0.1168.33 2019-02-04
------------------------------

Add support for static instance IP addresses
Improve instance management

Version 1.0.1155.32 2019-01-22
------------------------------

Add support for Oracle Cloud archive storage

Version 1.0.1154.31 2019-01-21
------------------------------

Improve instance startup

Version 1.0.1154.28 2019-01-21
------------------------------

Improve instance management

Version 1.0.1153.36 2019-01-20
------------------------------

Improve storage management

Version 1.0.1153.8 2019-01-20
-----------------------------

Add storage class to images

Version 1.0.1151.28 2019-01-18
------------------------------

Improve instance destroy

Version 1.0.1150.31 2019-01-17
------------------------------

Add copy to clipboard to web console

Version 1.0.1149.32 2019-01-16
------------------------------

Add automatic backup scheduling

Version 1.0.1147.30 2019-01-14
------------------------------

Add disk backup and restore

Version 1.0.1144.28 2019-01-11
------------------------------

Jumbo frames support
Instance management interface improvements

Version 1.0.1142.87 2019-01-09
------------------------------

Reliability improvements

Version 1.0.1141.35 2019-01-08
------------------------------

Improve instance management

Version 1.0.1140.33 2019-01-07
------------------------------

Add instance and disk delete protection
Web interface improvements

Version 1.0.1135.30 2019-01-02
------------------------------

Node management improvements

Version 1.0.1134.7 2019-01-01
-----------------------------

Improve node scalability
Improve firewall performance

Version 1.0.1129.93 2018-12-27
------------------------------

Linked disk improvements

Version 1.0.1129.29 2018-12-27
------------------------------

Add support for multiple network interfaces
Add support for linked disk images

Version 1.0.1124.31 2018-12-22
------------------------------

Improve instances interface in web console

Version 1.0.1118.32 2018-12-16
------------------------------

Virtual machine improvements

Version 1.0.1108.99 2018-12-06
------------------------------

Fix issue with Azure single sign-on

Version 1.0.1091.33 2018-11-19
------------------------------

Initial release


================================================
FILE: LICENSE
================================================
Copyright (c) 2013-2026 Pritunl

                               LICENSE SUMMARY

* License does not expire
* Can be used on unlimited sites, servers
* Source-code or binary products cannot be resold or distributed
* Non-commercial use only
* Can modify source-code but cannot distribute modifications (derivative works)

                                  PREAMBLE

This Agreement, signed on Nov 12, 2014 [hereinafter: Effective Date] governs
the relationship between you, a private person, (hereinafter: Licensee) and
Pritunl, a private person whose principal place of business is United States
(Hereinafter: Licensor). This Agreement sets the terms, rights, restrictions
and obligations on using [Pritunl] (hereinafter: The Software) created and
owned by Licensor, as detailed herein

                                LICENSE GRANT

Licensor hereby grants Licensee a Personal, Non-assignable &
non-transferable, Non-commercial, Royalty free, Without the rights to create
derivative works, Non-exclusive license, all with accordance with the terms
set forth and other legal restrictions set forth in 3rd party software used
while running Software.

Limited: Licensee may use Software for the purpose of:

* Running Software on Licensee's Website[s] and Server[s]
* Allowing 3rd Parties to run Software on Licensee's Website[s] and Server[s]
* Publishing Software's output to Licensee and 3rd Parties
* Modify Software to suit Licensee's needs and specifications.

Non Assignable & Non-Transferable: Licensee may not assign or transfer his
rights and duties under this license.

Non-Commercial: Licensee may not use Software for commercial purposes. for the
purpose of this license, commercial purposes means that a 3rd party has to pay
in order to access Software or that the Website that runs Software is behind a
paywall.

                             TERM & TERMINATION

The Term of this license shall be until terminated. Licensor may terminate
this Agreement, including Licensee's license in the case where Licensee:

* became insolvent or otherwise entered into any liquidation process; or
exported The Software to any jurisdiction where licensor may not enforce his
rights under this agreements in; or
* Licensee was in breach of any of this license's terms and conditions and
such breach was not cured, immediately upon notification; or
* Licensee in breach of any of the terms of clause 2 to this license; or
* Licensee otherwise entered into any arrangement which caused Licensor to be
unable to enforce his rights under this License.

                        UPGRADES, UPDATES AND FIXES

Licensor may provide Licensee, from time to time, with Upgrades, Updates or
Fixes, as detailed herein and according to his sole discretion. Licensee
hereby warrants to keep The Software up-to-date and install all relevant
updates and fixes, and may, at his sole discretion, purchase upgrades,
according to the rates set by Licensor. Licensor shall provide any update or
Fix free of charge; however, nothing in this Agreement shall require Licensor
to provide Updates or Fixes.

Upgrades: for the purpose of this license, an Upgrade shall be a material
amendment in The Software, which contains new features and or major
performance improvements and shall be marked as a new version number. For
example, should Licensee purchase The Software under version 1.X.X, an upgrade
shall commence under number 2.0.0.

Updates: for the purpose of this license, an update shall be a minor amendment
in The Software, which may contain new features or minor improvements and
shall be marked as a new sub-version number. For example, should Licensee
purchase The Software under version 1.1.X, an upgrade shall commence under
number 1.2.0.

Fix: for the purpose of this license, a fix shall be a minor amendment in The
Software, intended to remove bugs or alter minor features which impair the The
Software's functionality. A fix shall be marked as a new sub-sub-version
number. For example, should Licensee purchase Software under version 1.1.1,
an upgrade shall commence under number 1.1.2.

                                  SUPPORT

Software is provided under an AS-IS basis and without any support, updates or
maintenance. Nothing in this Agreement shall require Licensor to provide
Licensee with support or fixes to any bug, failure, mis-performance or other
defect in The Software.

Bug Notification: Licensee may provide Licensor of details regarding any bug,
defect or failure in The Software promptly and with no delay from such event;
Licensee shall comply with Licensor's request for information regarding bugs,
defects or failures and furnish him with information, screenshots and try to
reproduce such bugs, defects or failures.

Feature Request: Licensee may request additional features in Software,
provided, however, that (i) Licensee shall waive any claim or right in such
feature should feature be developed by Licensor; (ii) Licensee shall be
prohibited from developing the feature, or disclose such feature request, or
feature, to any 3rd party directly competing with Licensor or any 3rd party
which may be, following the development of such feature, in direct competition
with Licensor; (iii) Licensee warrants that feature does not infringe any 3rd
party patent, trademark, trade-secret or any other intellectual property
right; and (iv) Licensee developed, envisioned or created the feature solely
by himself.

Contribution: Licensee may submit additional code for the Software,
provided, however, that (i) Licensee hereby irrevocably assigns all right,
title, and interest in such contribution to Licensor upon submission; (ii)
Licensee hereby grants Licensor a perpetual, worldwide, royalty-free,
irrevocable license to use, modify, sublicense, and relicense such
contribution under any license terms Licensor chooses, including without
limitation less restrictive licenses such as AGPL; and (iii) Licensee
represents and warrants that the contribution is Licensee's original work
and does not infringe upon any third-party intellectual property rights; and
(iv) Licensee also waives any moral rights in the contribution to the extent
permitted by law.

                                 LIABILITY

To the extent permitted under Law, The Software is provided under an AS-IS
basis. Licensor shall never, and without any limit, be liable for any damage,
cost, expense or any other payment incurred by Licensee as a result of
Software's actions, failure, bugs and/or any other interaction between The
Software  and Licensee's end-equipment, computers, other software or any 3rd
party, end-equipment, computer or services.  Moreover, Licensor shall never be
liable for any defect in source code written by Licensee when relying on The
Software or using The Software's source code.

                                 WARRANTY

Intellectual Property: Licensor hereby warrants that The Software does not
violate or infringe any 3rd party claims in regards to intellectual property,
patents and/or trademarks and that to the best of its knowledge no legal
action has been taken against it for any infringement or violation of any 3rd
party intellectual property rights.

No-Warranty: The Software is provided without any warranty; Licensor hereby
disclaims any warranty that The Software shall be error free, without defects
or code which may cause damage to Licensee's computers or to Licensee, and
that Software shall be functional. Licensee shall be solely liable to any
damage, defect or loss incurred as a result of operating software and
undertake the risks contained in running The Software on License's Server[s]
and Website[s].

Prior Inspection: Licensee hereby states that he inspected The Software
thoroughly and found it satisfactory and adequate to his needs, that it does
not interfere with his regular operation and that it does meet the standards
and scope of his computer systems and architecture. Licensee found that The
Software interacts with his development, website and server environment and
that it does not infringe any of End User License Agreement of any software
Licensee may use in performing his services. Licensee hereby waives any claims
regarding The Software's incompatibility, performance, results and features,
and warrants that he inspected the The Software.

                               INDEMNIFICATION

Licensee hereby warrants to hold Licensor harmless and indemnify Licensor for
any lawsuit brought against it in regards to Licensee's use of The Software in
means that violate, breach or otherwise circumvent this license, Licensor's
intellectual property rights or Licensor's title in The Software. Licensor
shall promptly notify Licensee in case of such legal action and request
Licensee's consent prior to any settlement in relation to such lawsuit or
claim.

                        GOVERNING LAW, JURISDICTION

Licensee hereby agrees not to initiate class-action lawsuits against Licensor
in relation to this license and to compensate Licensor for any legal fees,
cost or attorney fees should any claim brought by Licensee against Licensor be
denied, in part or in full.


================================================
FILE: README.md
================================================
# pritunl-cloud: declarative kvm virtualization

[![github](https://img.shields.io/badge/github-pritunl-181717.svg?style=flat)](https://github.com/pritunl)
[![twitter](https://img.shields.io/badge/twitter-pritunl-55acee.svg?style=flat)](https://twitter.com/pritunl)
[![substack](https://img.shields.io/badge/substack-pritunl-ff6719.svg?style=flat)](https://pritunl.substack.com/)
[![forum](https://img.shields.io/badge/discussion-forum-ffffff.svg?style=flat)](https://forum.pritunl.com)

[Pritunl-Cloud](https://cloud.pritunl.com) is a declarative KVM virtualization
platform with shell and python based live updating templates. Documentation
and more information can be found at
[docs.pritunl.com](https://docs.pritunl.com/kb/cloud)

[![pritunl](img/logo_code.png)](https://docs.pritunl.com/kb/cloud)

## Install from Source

```bash
# Install Required Tools
sudo dnf -y install git-core iptables net-tools ipset ipvsadm xorriso qemu-kvm qemu-img swtpm-tools

sudo rm -rf /usr/local/go
wget https://go.dev/dl/go1.25.5.linux-amd64.tar.gz
echo "9e9b755d63b36acf30c12a9a3fc379243714c1c6d3dd72861da637f336ebb35b go1.25.5.linux-amd64.tar.gz" | sha256sum -c - && sudo tar -C /usr/local -xf go1.25.5.linux-amd64.tar.gz
rm -f go1.25.5.linux-amd64.tar.gz

tee -a ~/.bashrc << EOF
export GOPATH=\$HOME/go
export GOROOT=/usr/local/go
export PATH=/usr/local/go/bin:\$PATH
EOF
source ~/.bashrc

# Install MongoDB
sudo dnf -y install podman

git clone https://github.com/pritunl/toolbox.git
cd toolbox/mongodb-container
sudo podman build --rm -t mongo .
cd

sudo mkdir /var/lib/mongo
sudo chown 277:277 /var/lib/mongo
sudo tee /etc/containers/systemd/mongodb-podman.container << EOF
[Unit]
Description=MongoDB Podman Service

[Container]
Image=localhost/mongo
ContainerName=mongodb
Environment=DB_NAME=pritunl-cloud
Environment=CACHE_SIZE=1
User=mongodb
Volume=/var/lib/mongo:/data/db:Z
PublishPort=127.0.0.1:27017:27017
PodmanArgs=--cpus=1 --memory=2g

[Service]
Restart=always

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl start mongodb-podman.service

sleep 3
sudo cat /var/lib/mongo/credentials.txt

# Build Pritunl Cloud (update with latest version from releases)
go install -v github.com/pritunl/pritunl-cloud@2.0.3616.97
go install -v github.com/pritunl/pritunl-cloud/redirect@2.0.3616.97
go install -v github.com/pritunl/pritunl-cloud/agent@2.0.3616.97
GOOS=freebsd GOARCH=amd64 go install -v github.com/pritunl/pritunl-cloud/agent@2.0.3616.97

# Install Systemd Units
sudo cp $(ls -d ~/go/pkg/mod/github.com/pritunl/pritunl-cloud@v* | sort -V | tail -n 1)/tools/pritunl-cloud.service /etc/systemd/system/
sudo cp $(ls -d ~/go/pkg/mod/github.com/pritunl/pritunl-cloud@v* | sort -V | tail -n 1)/tools/pritunl-cloud-redirect.socket /etc/systemd/system/
sudo cp $(ls -d ~/go/pkg/mod/github.com/pritunl/pritunl-cloud@v* | sort -V | tail -n 1)/tools/pritunl-cloud-redirect.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo useradd -r -s /sbin/nologin -c 'Pritunl web server' pritunl-cloud-web

# Install Pritunl Cloud
sudo mkdir -p /usr/share/pritunl-cloud/www/
sudo cp -r $(ls -d ~/go/pkg/mod/github.com/pritunl/pritunl-cloud@v* | sort -V | tail -n 1)/www/dist/. /usr/share/pritunl-cloud/www/
sudo cp ~/go/bin/pritunl-cloud /usr/bin/pritunl-cloud
sudo cp ~/go/bin/redirect /usr/bin/pritunl-cloud-redirect
sudo cp ~/go/bin/agent /usr/bin/pritunl-cloud-agent
sudo cp ~/go/bin/freebsd_amd64/agent /usr/bin/pritunl-cloud-agent-bsd

sudo systemctl enable --now pritunl-cloud
```

## License

Please refer to the [`LICENSE`](LICENSE) file for a copy of the license.


================================================
FILE: acme/acme.go
================================================
package acme

import (
	"context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"strings"
	"time"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/certificate"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/dns"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/secret"
	"github.com/pritunl/pritunl-cloud/settings"
	"github.com/sirupsen/logrus"
	"golang.org/x/crypto/acme"
)

func Generate(db *database.Database, cert *certificate.Certificate) (
	err error) {

	acmeType := cert.AcmeType
	if acmeType == "" {
		acmeType = certificate.AcmeHTTP
	}

	acmeAuth := cert.AcmeAuth

	logrus.WithFields(logrus.Fields{
		"certificate": cert.Name,
		"domains":     cert.AcmeDomains,
		"acme_type":   acmeType,
		"acme_auth":   acmeAuth,
	}).Info("acme: Generating acme certificate")

	if cert.AcmeDomains == nil || len(cert.AcmeDomains) == 0 {
		err = &errortypes.UnknownError{
			errors.Wrap(err, "acme: No acme domains"),
		}
		return
	}

	var dnsSvc dns.Service
	if acmeType == certificate.AcmeDNS {
		var secr *secret.Secret
		if cert.Organization.IsZero() {
			secr, err = secret.Get(db, cert.AcmeSecret)
			if err != nil {
				return
			}
		} else {
			secr, err = secret.GetOrg(db, cert.Organization, cert.AcmeSecret)
			if err != nil {
				return
			}
		}

		if secr == nil {
			err = &errortypes.UnknownError{
				errors.Wrap(err, "acme: ACME secret not found"),
			}
			return
		}

		if acmeAuth == certificate.AcmeAWS {
			dnsSvc = &dns.Aws{}
		} else if acmeAuth == certificate.AcmeCloudflare {
			dnsSvc = &dns.Cloudflare{}
		} else if acmeAuth == certificate.AcmeOracleCloud {
			dnsSvc = &dns.Oracle{}
		} else if acmeAuth == certificate.AcmeGoogleCloud {
			dnsSvc = &dns.Google{}
		} else {
			err = &errortypes.UnknownError{
				errors.Wrapf(err,
					"acme: Unknown acme auth type %s", acmeAuth),
			}
			return
		}

		err = dnsSvc.Connect(db, secr)
		if err != nil {
			return
		}
	}

	var acctKey *rsa.PrivateKey

	if cert.AcmeAccount != "" {
		acctBlock, _ := pem.Decode([]byte(cert.AcmeAccount))
		if acctBlock == nil {
			err = &errortypes.ParseError{
				errors.New("acme: Failed to decode account key"),
			}
			return
		}

		acctKey, err = x509.ParsePKCS1PrivateKey(acctBlock.Bytes)
		if err != nil {
			err = &errortypes.ParseError{
				errors.Wrap(err, "acme: Failed to parse account key"),
			}
			return
		}
	} else {
		acctKey, err = rsa.GenerateKey(rand.Reader, 2048)
		if err != nil {
			err = &errortypes.ReadError{
				errors.Wrap(err, "acme: Failed to generate account key"),
			}
			return
		}

		acctBlock := &pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: x509.MarshalPKCS1PrivateKey(acctKey),
		}

		cert.AcmeAccount = string(pem.EncodeToMemory(acctBlock))
		err = cert.CommitFields(db, set.NewSet("acme_account"))
		if err != nil {
			return
		}
	}

	acct := &acme.Account{}

	client := &acme.Client{
		DirectoryURL: AcmeDirectory,
		Key:          acctKey,
	}

	_, err = client.Register(context.Background(), acct, acme.AcceptTOS)
	if err != nil {
		if err == acme.ErrAccountAlreadyExists {
			err = nil
		} else {
			err = &errortypes.RequestError{
				errors.Wrap(err, "acme: Failed to register account"),
			}
			return
		}
	}

	order, err := client.AuthorizeOrder(
		context.Background(), acme.DomainIDs(cert.AcmeDomains...))
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "acme: Failed to authorize order"),
		}
		return
	}

	if order.Status == acme.StatusReady {
		err = create(db, cert, client, order)
		if err != nil {
			return
		}

		return
	} else if order.Status != acme.StatusPending {
		err = &errortypes.RequestError{
			errors.Newf(
				"acme: Authorize order status '%s' not pending",
				order.Status,
			),
		}
		return
	}

	authzUrls := order.AuthzURLs

	for _, authzUrl := range authzUrls {
		authz, e := client.GetAuthorization(
			context.Background(), authzUrl)
		if e != nil {
			err = &errortypes.RequestError{
				errors.Wrap(e, "acme: Failed to get authorization"),
			}
			return
		}

		if authz.Status != acme.StatusPending {
			continue
		}

		var authzChal *acme.Challenge
		for _, c := range authz.Challenges {
			if acmeType == certificate.AcmeDNS {
				if c.Type == "dns-01" {
					authzChal = c
					break
				}
			} else {
				if c.Type == "http-01" {
					authzChal = c
					break
				}
			}
		}

		if authzChal == nil {
			revoke(client, authzUrls)

			err = &errortypes.RequestError{
				errors.New(
					"acme: Authorization challenge not available"),
			}
			return
		}

		var chal *Challenge
		var chalToken string
		var chalDomain string
		if acmeType == certificate.AcmeDNS {
			chalToken, err = client.DNS01ChallengeRecord(authzChal.Token)
			if err != nil {
				err = &errortypes.RequestError{
					errors.Wrap(err, "acme: Challenge record error"),
				}
				return
			}

			chalDomain = fmt.Sprintf(
				"_acme-challenge.%s.", authz.Identifier.Value)

			ops := []*dns.Operation{
				&dns.Operation{
					Operation: dns.UPSERT,
					Value:     "\"" + chalToken + "\"",
				},
			}

			err = dnsSvc.DnsCommit(db, chalDomain, "TXT", ops)
			if err != nil {
				return
			}

			defer func() {
				delOps := []*dns.Operation{
					&dns.Operation{
						Operation: dns.DELETE,
						Value:     "\"" + chalToken + "\"",
					},
				}

				e := dnsSvc.DnsCommit(db, chalDomain, "TXT", delOps)
				if e != nil {
					logrus.WithFields(logrus.Fields{
						"certificate": cert.Name,
						"domain":      chalDomain,
						"acme_type":   acmeType,
						"acme_auth":   acmeAuth,
						"error":       e,
					}).Error("acme: Failed to remove DNS TXT record")
				}
			}()

			matched, e := DnsTxtWait(chalDomain, chalToken)
			if e != nil {
				err = e
				return
			}

			if !matched {
				logrus.WithFields(logrus.Fields{
					"certificate": cert.Name,
					"domain":      chalDomain,
					"acme_type":   acmeType,
					"acme_auth":   acmeAuth,
				}).Warning("acme: Local DNS TXT test lookup failed")
			}

			time.Sleep(time.Duration(settings.Acme.DnsDelay) * time.Second)
		} else {
			resp, e := client.HTTP01ChallengeResponse(authzChal.Token)
			if e != nil {
				revoke(client, authzUrls)

				err = &errortypes.RequestError{
					errors.Wrap(e, "acme: Challenge response failed"),
				}
				return
			}

			chal = &Challenge{
				Id:        authzChal.Token,
				Resource:  resp,
				Timestamp: time.Now(),
			}

			err = chal.Insert(db)
			if err != nil {
				return
			}

			chalMsg := &ChallengeMsg{
				Token:    authzChal.Token,
				Response: resp,
			}

			err = chalMsg.Publish(db)
			if err != nil {
				return
			}

			time.Sleep(300 * time.Millisecond)
		}

		_, err = client.Accept(context.Background(), authzChal)
		if err != nil {
			revoke(client, authzUrls)

			err = &errortypes.RequestError{
				errors.Wrap(err, "acme: Authorization accept failed"),
			}
			return
		}

		_, err = client.WaitAuthorization(
			context.Background(), authzChal.URI)
		if err != nil {
			revoke(client, authzUrls)

			err = &errortypes.RequestError{
				errors.Wrap(err, "acme: Authorization wait failed"),
			}
			return
		}

		if chal != nil {
			err = chal.Remove(db)
			if err != nil {
				revoke(client, authzUrls)

				return
			}
		}
	}

	order, err = client.WaitOrder(context.Background(), order.URI)
	if err != nil {
		revoke(client, authzUrls)

		err = &errortypes.RequestError{
			errors.Wrap(err, "acme: Order wait failed"),
		}
		return
	}

	if order.Status != acme.StatusReady {
		err = &errortypes.RequestError{
			errors.Newf(
				"acme: Authorize order status '%s' not ready",
				order.Status,
			),
		}
		return
	}

	err = create(db, cert, client, order)
	if err != nil {
		return
	}

	return
}

func create(db *database.Database, cert *certificate.Certificate,
	client *acme.Client, order *acme.Order) (err error) {

	var csr []byte
	var keyPem []byte

	if settings.System.AcmeKeyAlgorithm == "ec" {
		csr, keyPem, err = newEcCsr(cert.AcmeDomains)
		if err != nil {
			return
		}
	} else {
		csr, keyPem, err = newRsaCsr(cert.AcmeDomains)
		if err != nil {
			return
		}
	}

	derChain, _, err := client.CreateOrderCert(
		context.Background(),
		order.FinalizeURL,
		csr,
		true,
	)
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "acme: Create order cert failed"),
		}
		return
	}

	certPem := ""

	for _, der := range derChain {
		certBlock := &pem.Block{
			Type:  "CERTIFICATE",
			Bytes: der,
		}

		if certPem != "" {
			certPem += "\n"
		}
		certPem += strings.TrimSpace(string(pem.EncodeToMemory(certBlock)))
	}

	cert.Key = strings.TrimSpace(string(keyPem))
	cert.Certificate = certPem
	cert.AcmeHash = cert.Hash()

	_, err = cert.Validate(db)
	if err != nil {
		return
	}

	err = cert.CommitFields(db, set.NewSet(
		"key", "certificate", "acme_hash", "info"))
	if err != nil {
		return
	}

	event.PublishDispatch(db, "certificate.change")

	return
}

func Renew(db *database.Database, cert *certificate.Certificate, force bool) (
	err error) {

	if cert.Type != certificate.LetsEncrypt {
		return
	}

	if force || cert.AcmeHash != cert.Hash() || (cert.Info != nil &&
		!cert.Info.ExpiresOn.IsZero() &&
		time.Until(cert.Info.ExpiresOn) < 168*time.Hour) {

		err = Generate(db, cert)
		if err != nil {
			return
		}
	}

	return
}

func RenewBackground(cert *certificate.Certificate, force bool) {
	go func() {
		db := database.GetDatabase()
		defer db.Close()

		err := Renew(db, cert, force)
		if err != nil {
			logrus.WithFields(logrus.Fields{
				"certificate_id":   cert.Id.Hex(),
				"certificate_name": cert.Name,
				"error":            err,
			}).Error("task: Failed to renew certificate")
		}
	}()
}


================================================
FILE: acme/challenge.go
================================================
package acme

import (
	"time"

	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/event"
)

type Challenge struct {
	Id        string    `bson:"_id"`
	Resource  string    `bson:"resource"`
	Timestamp time.Time `bson:"timestamp"`
}

func (c *Challenge) Insert(db *database.Database) (err error) {
	coll := db.AcmeChallenges()

	_, err = coll.InsertOne(db, c)
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}

func (c *Challenge) Remove(db *database.Database) (err error) {
	coll := db.AcmeChallenges()

	_, err = coll.DeleteOne(db, &bson.M{
		"_id": c.Id,
	})
	if err != nil {
		err = database.ParseError(err)
		switch err.(type) {
		case *database.NotFoundError:
			err = nil
		default:
			return
		}
	}

	return
}

type ChallengeMsg struct {
	Token    string `bson:"token" json:"token"`
	Response string `bson:"response" json:"response"`
}

func (c *ChallengeMsg) Publish(db *database.Database) (err error) {
	err = event.Publish(db, "acme", c)
	if err != nil {
		return
	}

	return
}


================================================
FILE: acme/constants.go
================================================
package acme

const (
	AcmeDirectory = "https://acme-v02.api.letsencrypt.org/directory"
	AcmePath      = "/.well-known/acme-challenge/"
)


================================================
FILE: acme/utils.go
================================================
package acme

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"net"
	"strings"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/settings"
	"golang.org/x/crypto/acme"
)

func revoke(client *acme.Client, authzUrls []string) {
	if authzUrls == nil {
		return
	}

	for _, authzUrl := range authzUrls {
		authz, err := client.GetAuthorization(
			context.Background(), authzUrl)
		if err != nil {
			continue
		}

		if authz.Status != acme.StatusPending {
			continue
		}

		_ = client.RevokeAuthorization(context.Background(), authzUrl)
	}
}

func ParsePath(path string) string {
	split := strings.SplitN(path, AcmePath, 2)
	if len(split) == 2 {
		return split[1]
	}
	return ""
}

func DnsTxtWait(domain, val string) (found bool, err error) {
	start := time.Now()
	iterDelay := time.Duration(settings.Acme.DnsRetryRate) * time.Second
	timeout := time.Duration(settings.Acme.DnsTimeout) * time.Second

	for i := 0; i < 60; i++ {
		if time.Since(start) > timeout {
			return
		}

		time.Sleep(iterDelay)

		records, e := net.LookupTXT(domain)
		if e != nil {
			continue
		}

		for _, record := range records {
			if record == val {
				found = true
				return
			}
		}
	}

	return
}

func GetChallenge(token string) (challenge *Challenge, err error) {
	db := database.GetDatabase()
	defer db.Close()

	coll := db.AcmeChallenges()
	challenge = &Challenge{}

	err = coll.FindOneId(token, challenge)
	if err != nil {
		return
	}

	return
}

func newRsaCsr(domains []string) (csr []byte, keyPem []byte, err error) {
	key, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "acme: Failed to generate private key"),
		}
		return
	}

	csrReq := &x509.CertificateRequest{
		SignatureAlgorithm: x509.SHA256WithRSA,
		PublicKeyAlgorithm: x509.RSA,
		PublicKey:          key.Public(),
		Subject: pkix.Name{
			CommonName: domains[0],
		},
		DNSNames: domains,
	}

	csr, err = x509.CreateCertificateRequest(rand.Reader, csrReq, key)
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "acme: Failed to create certificate request"),
		}
		return
	}

	certKeyByte := x509.MarshalPKCS1PrivateKey(key)

	certKeyBlock := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: certKeyByte,
	}

	keyPem = pem.EncodeToMemory(certKeyBlock)

	return
}

func newEcCsr(domains []string) (csr []byte, keyPem []byte, err error) {
	key, err := ecdsa.GenerateKey(
		elliptic.P384(),
		rand.Reader,
	)
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "acme: Failed to generate private key"),
		}
		return
	}

	csrReq := &x509.CertificateRequest{
		SignatureAlgorithm: x509.ECDSAWithSHA256,
		PublicKeyAlgorithm: x509.ECDSA,
		PublicKey:          key.Public(),
		Subject: pkix.Name{
			CommonName: domains[0],
		},
		DNSNames: domains,
	}

	csr, err = x509.CreateCertificateRequest(rand.Reader, csrReq, key)
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "acme: Failed to create certificate request"),
		}
		return
	}

	certKeyByte, err := x509.MarshalECPrivateKey(key)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "acme: Failed to parse private key"),
		}
		return
	}

	certKeyBlock := &pem.Block{
		Type:  "EC PRIVATE KEY",
		Bytes: certKeyByte,
	}

	keyPem = pem.EncodeToMemory(certKeyBlock)

	return
}


================================================
FILE: advisory/advisory.go
================================================
package advisory

import (
	"net/http"
	"time"

	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo/options"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/settings"
)

var client = &http.Client{
	Timeout: 10 * time.Second,
}

type Advisory struct {
	Id              string    `bson:"id" json:"id"`
	Timestamp       time.Time `bson:"timestamp" json:"timestamp"`
	Status          string    `bson:"status" json:"status"`
	Description     string    `bson:"description" json:"description"`
	Score           float64   `bson:"score" json:"score"`
	Severity        string    `bson:"severity" json:"severity"`
	Vector          string    `bson:"vector" json:"vector"`
	Complexity      string    `bson:"complexity" json:"complexity"`
	Privileges      string    `bson:"privileges" json:"privileges"`
	Interaction     string    `bson:"interaction" json:"interaction"`
	Scope           string    `bson:"scope" json:"scope"`
	Confidentiality string    `bson:"confidentiality" json:"confidentiality"`
	Integrity       string    `bson:"integrity" json:"integrity"`
	Availability    string    `bson:"availability" json:"availability"`
}

func (a *Advisory) Validate(db *database.Database) (
	errData *errortypes.ErrorData, err error) {

	if a.Id == "" {
		errData = &errortypes.ErrorData{
			Error:   "id_required",
			Message: "Missing required advisory ID",
		}
		return
	}

	if a.Timestamp.IsZero() {
		a.Timestamp = time.Now()
	}

	if !cveIdReg.MatchString(a.Id) {
		errData = &errortypes.ErrorData{
			Error:   "id_invalid",
			Message: "Invalid advisory ID",
		}
		return
	}

	if a.Status != "" && !ValidStatuses.Contains(a.Status) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_status",
			Message: "Invalid advisory status",
		}
		return
	}

	if a.Score < 0 || a.Score > 10 {
		errData = &errortypes.ErrorData{
			Error:   "invalid_score",
			Message: "Advisory score must be between 0 and 10",
		}
		return
	}

	if a.Severity != "" && !ValidSeverities.Contains(a.Severity) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_severity",
			Message: "Invalid advisory severity",
		}
		return
	}

	if a.Vector != "" && !ValidVectors.Contains(a.Vector) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_vector",
			Message: "Invalid advisory attack vector",
		}
		return
	}

	if a.Complexity != "" && !ValidComplexities.Contains(a.Complexity) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_complexity",
			Message: "Invalid advisory attack complexity",
		}
		return
	}

	if a.Privileges != "" && !ValidPrivileges.Contains(a.Privileges) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_privileges",
			Message: "Invalid advisory privileges required",
		}
		return
	}

	if a.Interaction != "" && !ValidInteractions.Contains(a.Interaction) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_interaction",
			Message: "Invalid advisory user interaction",
		}
		return
	}

	if a.Scope != "" && !ValidScopes.Contains(a.Scope) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_scope",
			Message: "Invalid advisory scope",
		}
		return
	}

	if a.Confidentiality != "" &&
		!ValidImpacts.Contains(a.Confidentiality) {

		errData = &errortypes.ErrorData{
			Error:   "invalid_confidentiality",
			Message: "Invalid advisory confidentiality impact",
		}
		return
	}

	if a.Integrity != "" && !ValidImpacts.Contains(a.Integrity) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_integrity",
			Message: "Invalid advisory integrity impact",
		}
		return
	}

	if a.Availability != "" && !ValidImpacts.Contains(a.Availability) {
		errData = &errortypes.ErrorData{
			Error:   "invalid_availability",
			Message: "Invalid advisory availability impact",
		}
		return
	}

	return
}

func (a *Advisory) IsFresh() bool {
	if a == nil {
		return false
	}

	if (a.Status == Analyzed || a.Status == Deferred) &&
		time.Since(a.Timestamp) < time.Duration(
			settings.Telemetry.NvdFinalTtl)*time.Second {

		return true
	}

	if time.Since(a.Timestamp) < time.Duration(
		settings.Telemetry.NvdTtl)*time.Second {

		return true
	}

	return false
}

func (a *Advisory) Commit(db *database.Database) (err error) {
	coll := db.Advisories()

	_, err = coll.UpdateOne(
		db,
		&bson.M{
			"_id": a.Id,
		},
		&bson.M{
			"$set": &bson.M{
				"timestamp":       a.Timestamp,
				"status":          a.Status,
				"description":     a.Description,
				"score":           a.Score,
				"severity":        a.Severity,
				"vector":          a.Vector,
				"complexity":      a.Complexity,
				"privileges":      a.Privileges,
				"interaction":     a.Interaction,
				"scope":           a.Scope,
				"confidentiality": a.Confidentiality,
				"integrity":       a.Integrity,
				"availability":    a.Availability,
			},
		},
		options.UpdateOne().SetUpsert(true),
	)
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: advisory/constants.go
================================================
package advisory

import (
	"regexp"

	"github.com/dropbox/godropbox/container/set"
)

const (
	None      = "none"
	Low       = "low"
	Medium    = "medium"
	High      = "high"
	Critical  = "critical"
	Network   = "network"
	Adjacent  = "adjacent"
	Local     = "local"
	Physical  = "physical"
	Required  = "required"
	Unchanged = "unchanged"
	Changed   = "changed"

	Analyzed         = "analyzed"
	AwaitingAnalysis = "awaiting_analysis"
	Rejected         = "rejected"
	Undergoing       = "undergoing_analysis"
	Modified         = "modified"
	Deferred         = "deferred"
	Pending          = "pending"

	nvdApi = "https://services.nvd.nist.gov/rest/json/cves/2.0"
)

var (
	cveIdReg = regexp.MustCompile(`^CVE-\d{4}-\d{4,}$`)

	ValidStatuses = set.NewSet(
		Analyzed,
		AwaitingAnalysis,
		Rejected,
		Undergoing,
		Modified,
		Deferred,
	)

	ValidSeverities = set.NewSet(
		None,
		Low,
		Medium,
		High,
		Critical,
	)

	ValidVectors = set.NewSet(
		Network,
		Adjacent,
		Local,
		Physical,
	)

	ValidComplexities = set.NewSet(
		Low,
		High,
	)

	ValidPrivileges = set.NewSet(
		None,
		Low,
		High,
	)

	ValidInteractions = set.NewSet(
		None,
		Required,
	)

	ValidScopes = set.NewSet(
		Unchanged,
		Changed,
	)

	ValidImpacts = set.NewSet(
		None,
		Low,
		High,
	)
)


================================================
FILE: advisory/utils.go
================================================
package advisory

import (
	"encoding/json"
	"net/http"
	"strings"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/settings"
)

var (
	lastCall time.Time
)

type nvdCvssData struct {
	VectorString          string  `json:"vectorString"`
	BaseScore             float64 `json:"baseScore"`
	BaseSeverity          string  `json:"baseSeverity"`
	AttackVector          string  `json:"attackVector"`
	AttackComplexity      string  `json:"attackComplexity"`
	PrivilegesRequired    string  `json:"privilegesRequired"`
	UserInteraction       string  `json:"userInteraction"`
	Scope                 string  `json:"scope"`
	ConfidentialityImpact string  `json:"confidentialityImpact"`
	IntegrityImpact       string  `json:"integrityImpact"`
	AvailabilityImpact    string  `json:"availabilityImpact"`
}

type nvdCvssMetric struct {
	Type     string      `json:"type"`
	CvssData nvdCvssData `json:"cvssData"`
}

type nvdMetrics struct {
	CvssMetricV31 []nvdCvssMetric `json:"cvssMetricV31"`
}

type nvdDescription struct {
	Lang  string `json:"lang"`
	Value string `json:"value"`
}

type nvdCve struct {
	ID           string           `json:"id"`
	VulnStatus   string           `json:"vulnStatus"`
	Descriptions []nvdDescription `json:"descriptions"`
	Metrics      nvdMetrics       `json:"metrics"`
}

type nvdVulnerability struct {
	Cve nvdCve `json:"cve"`
}

type nvdResponse struct {
	TotalResults    int                `json:"totalResults"`
	Vulnerabilities []nvdVulnerability `json:"vulnerabilities"`
}

func normalizeStatus(status string) string {
	switch status {
	case "Analyzed":
		return Analyzed
	case "Awaiting Analysis":
		return AwaitingAnalysis
	case "Rejected":
		return Rejected
	case "Undergoing Analysis":
		return Undergoing
	case "Modified":
		return Modified
	case "Deferred":
		return Deferred
	default:
		return strings.ToLower(strings.ReplaceAll(status, " ", "_"))
	}
}

func normalizeValue(val string) string {
	switch strings.ToUpper(val) {
	case "NONE":
		return None
	case "LOW":
		return Low
	case "MEDIUM":
		return Medium
	case "HIGH":
		return High
	case "CRITICAL":
		return Critical
	case "NETWORK":
		return Network
	case "ADJACENT_NETWORK", "ADJACENT":
		return Adjacent
	case "LOCAL":
		return Local
	case "PHYSICAL":
		return Physical
	case "REQUIRED":
		return Required
	case "UNCHANGED":
		return Unchanged
	case "CHANGED":
		return Changed
	default:
		return strings.ToLower(val)
	}
}

func getOne(db *database.Database, query *bson.M) (adv *Advisory, err error) {
	coll := db.Advisories()
	adv = &Advisory{}

	err = coll.FindOne(db, query).Decode(adv)
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}

func getOneNvd(db *database.Database, cveId string) (
	adv *Advisory, err error) {

	req, err := http.NewRequest("GET", nvdApi, nil)
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "advisory: Failed to create request"),
		}
		return
	}

	query := req.URL.Query()
	query.Set("cveId", cveId)
	req.URL.RawQuery = query.Encode()

	nvdApiKey := settings.Telemetry.NvdApiKey
	if nvdApiKey != "" {
		req.Header.Set("apiKey", nvdApiKey)
	}

	resp, err := client.Do(req)
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "advisory: Request failed"),
		}
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		err = &errortypes.RequestError{
			errors.Newf("advisory: Bad status status %d", resp.StatusCode),
		}
		return
	}

	nvdResp := &nvdResponse{}
	err = json.NewDecoder(resp.Body).Decode(nvdResp)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "advisory: Failed to decode response"),
		}
		return
	}

	if nvdResp.TotalResults == 0 || len(nvdResp.Vulnerabilities) == 0 {
		err = &errortypes.NotFoundError{
			errors.New("advisory: Not found"),
		}
		return
	}

	cve := nvdResp.Vulnerabilities[0].Cve

	adv = &Advisory{
		Id:        strings.ToUpper(cve.ID),
		Timestamp: time.Now(),
		Status:    normalizeStatus(cve.VulnStatus),
	}

	for _, desc := range cve.Descriptions {
		if desc.Lang == "en" {
			adv.Description = desc.Value
			break
		}
	}

	metrics := cve.Metrics.CvssMetricV31
	if len(metrics) > 0 {
		var cvss *nvdCvssMetric

		for i := range metrics {
			if metrics[i].Type == "Primary" {
				cvss = &metrics[i]
				break
			}
		}
		if cvss == nil {
			cvss = &metrics[0]
		}

		adv.Score = cvss.CvssData.BaseScore
		adv.Severity = normalizeValue(cvss.CvssData.BaseSeverity)
		adv.Vector = normalizeValue(cvss.CvssData.AttackVector)
		adv.Complexity = normalizeValue(cvss.CvssData.AttackComplexity)
		adv.Privileges = normalizeValue(cvss.CvssData.PrivilegesRequired)
		adv.Interaction = normalizeValue(cvss.CvssData.UserInteraction)
		adv.Scope = normalizeValue(cvss.CvssData.Scope)
		adv.Confidentiality = normalizeValue(
			cvss.CvssData.ConfidentialityImpact)
		adv.Integrity = normalizeValue(cvss.CvssData.IntegrityImpact)
		adv.Availability = normalizeValue(cvss.CvssData.AvailabilityImpact)
	}

	errData, err := adv.Validate(db)
	if err != nil {
		return
	}
	if errData != nil {
		err = errData.GetError()
		return
	}

	err = adv.Commit(db)
	if err != nil {
		return
	}

	return
}

func GetOneLimit(db *database.Database, cveId string) (
	adv *Advisory, err error) {

	adv, err = getOne(db, &bson.M{
		"_id": cveId,
	})
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			adv = nil
		} else {
			return
		}
	}

	if adv.IsFresh() {
		return
	}

	since := time.Since(lastCall)
	var limit time.Duration
	if settings.Telemetry.NvdApiKey != "" {
		limit = time.Duration(settings.Telemetry.NvdApiAuthLimit) * time.Second
	} else {
		limit = time.Duration(settings.Telemetry.NvdApiLimit) * time.Second
	}
	if since < limit {
		time.Sleep(limit - since)
	}
	lastCall = time.Now()

	adv, err = getOneNvd(db, cveId)
	if err != nil {
		return
	}

	return
}

func GetOne(db *database.Database, cveId string) (adv *Advisory, err error) {
	adv, err = getOne(db, &bson.M{
		"_id": cveId,
	})
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			adv = nil
		} else {
			return
		}
	}

	if adv.IsFresh() {
		return
	}

	adv, err = getOneNvd(db, cveId)
	if err != nil {
		return
	}

	return
}

func Remove(db *database.Database, advId bson.ObjectID) (err error) {
	coll := db.Advisories()

	_, err = coll.DeleteOne(db, &bson.M{
		"_id": advId,
	})
	if err != nil {
		err = database.ParseError(err)
		if _, ok := err.(*database.NotFoundError); ok {
			err = nil
		} else {
			return
		}
	}

	return
}


================================================
FILE: agent/agent.go
================================================
package main

import (
	"flag"
	"fmt"
	"os"
	"runtime/debug"
	"strings"
	"syscall"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/agent/constants"
	"github.com/pritunl/pritunl-cloud/agent/imds"
	"github.com/pritunl/pritunl-cloud/agent/utils"
	"github.com/pritunl/pritunl-cloud/engine"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/imds/types"
	pritunl_utils "github.com/pritunl/pritunl-cloud/utils"
	"github.com/pritunl/tools/logger"
)

const help = `
Usage: pci COMMAND

Commands:
  get          Get value from IMDS
  image        Sanitize host files and initiate shutdown for imaging
  version      Show version
`

var (
	daemon = flag.Bool("daemon", false, "Fork agent to background")
)

func main() {
	defer func() {
		panc := recover()
		if panc != nil {
			logger.WithFields(logger.Fields{
				"trace": string(debug.Stack()),
				"panic": panc,
			}).Error("agent: Panic in main")
			time.Sleep(3 * time.Second)
			os.Exit(1)
		}
	}()
	flag.Usage = func() {
		fmt.Printf(help)
	}

	flag.Parse()

	logger.Init(
		logger.SetTimeFormat(""),
	)

	logger.AddHandler(func(record *logger.Record) {
		fmt.Print(record.String())
	})

	command := flag.Arg(0)
	if command == "engine" || command == "agent" {
		envStateData := os.Getenv("IMDS_STATE")
		envStateDatas := strings.Split(envStateData, ":")
		if len(envStateDatas) != 2 {
			fmt.Println("pritunl-cloud-agent: Invalid state")
			os.Exit(1)
			return
		}
		stage := envStateDatas[0]
		envState := envStateDatas[1]

		if stage == "run" {
			err := imds.SetState(envState)
			if err != nil {
				logger.WithFields(logger.Fields{
					"error": err,
				}).Error("agent: Failed to write imds state")
				utils.DelayExit(1, 1*time.Second)
				return
			}
		} else {
			confState := imds.GetState()

			if envState != "" && confState != envState {
				fmt.Println("pritunl-cloud-agent: Waiting for state")
				os.Exit(0)
				return
			}
		}

		if *daemon {
			err := daemonFork()
			if err != nil {
				logger.WithFields(logger.Fields{
					"error": err,
				}).Error("agent: Failed to fork to background")
				utils.DelayExit(1, 1*time.Second)
				return
			}
		}
	}

	switch command {
	case "get":
		ids := &imds.Imds{}

		err := ids.Init(nil)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Initialize failed")
			utils.DelayExit(1, 1*time.Second)
			return
		}
		defer ids.Close()

		val, err := ids.Get(flag.Arg(1))
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Get imds failed")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		fmt.Print(val)

		break
	case "engine":
		eng := &engine.Engine{
			OnStatus: imds.SetStatus,
		}
		ids := &imds.Imds{}

		err := ids.Init(eng)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to init imds")
			utils.DelayExit(1, 1*time.Second)
			return
		}
		defer ids.Close()

		err = ids.OpenLog()
		if err != nil {
			return
		}

		err = ids.SyncReady(5 * time.Minute)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to sync imds initial")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		image := false
		phase := engine.Reboot
		switch flag.Arg(1) {
		case engine.Image:
			image = true
			phase = engine.Initial
			break
		case engine.Initial:
			phase = engine.Initial
			break
		}

		err = eng.Init()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to init engine")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		data, err := utils.Read("/etc/pritunl-deploy.md")
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to read deploy spec")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		blocks, err := engine.Parse(data)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to parse deploy spec")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		ids.RunSync(image)

		runStatus := types.Running
		fatal, err := eng.Run(phase, blocks)
		if err != nil {
			runStatus = types.Fault
			if fatal {
				logger.WithFields(logger.Fields{
					"error": err,
				}).Error("agent: Fatal initial engine run error")
				utils.DelayExit(1, 1*time.Second)
				return
			} else {
				logger.WithFields(logger.Fields{
					"error": err,
				}).Error("agent: Non-fatal initial engine run error")
				err = nil
			}
		}

		if !image {
			ids.SetInitialized()

			err = ids.SyncStatus(runStatus)
			if err != nil {
				logger.WithFields(logger.Fields{
					"error": err,
				}).Error("agent: Failed to sync status")
				utils.DelayExit(1, 1*time.Second)
				return
			}

			err = ids.Wait()
			if err != nil {
				logger.WithFields(logger.Fields{
					"error": err,
				}).Error("agent: Failed to run")
				utils.DelayExit(1, 1*time.Second)
				return
			}
		}

		time.Sleep(500 * time.Millisecond)

		_, err = ids.Sync()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to sync")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		break
	case "agent":
		ids := &imds.Imds{}

		err := ids.Init(nil)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to init imds")
			utils.DelayExit(1, 1*time.Second)
			return
		}
		defer ids.Close()

		err = ids.OpenLog()
		if err != nil {
			return
		}

		err = ids.SyncReady(5 * time.Minute)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to sync imds initial")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		ids.RunSync(false)
		ids.SetInitialized()

		err = ids.SyncStatus(types.Running)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to sync status")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		err = ids.Wait()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to run")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		time.Sleep(500 * time.Millisecond)

		_, err = ids.Sync()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Failed to sync")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		break
	case "image":
		ids := &imds.Imds{}

		err := ids.Init(nil)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Iniatilize failed")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		err = utils.Sanitize()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Sanitize failed")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		err = ids.SyncStatus(types.Imaged)
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Sync status failed")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		err = utils.SanitizeImds()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("agent: Sanitize imds failed")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		break
	case "status":
		mem, err := pritunl_utils.GetMemInfo()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("imds: Failed to get memory")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		fmt.Println("Memory Information:")
		fmt.Printf("  Total Memory:           %d KB\n", mem.Total)
		fmt.Printf("  Free Memory:            %d KB\n", mem.Free)
		fmt.Printf("  Available Memory:       %d KB\n", mem.Available)
		fmt.Printf("  Buffers:                %d KB\n", mem.Buffers)
		fmt.Printf("  Cached:                 %d KB\n", mem.Cached)
		fmt.Printf("  Used Memory:            %d KB\n", mem.Used)
		fmt.Printf("  Used Percentage:        %.2f%%\n", mem.UsedPercent)
		fmt.Printf("  Dirty:                  %d KB\n", mem.Dirty)
		fmt.Println("\nSwap Information:")
		fmt.Printf("  Swap Total:             %d KB\n", mem.SwapTotal)
		fmt.Printf("  Swap Free:              %d KB\n", mem.SwapFree)
		fmt.Printf("  Swap Used:              %d KB\n", mem.SwapUsed)
		fmt.Printf("  Swap Used Percentage:   %.2f%%\n", mem.SwapUsedPercent)
		fmt.Println("\nHugePages Information:")
		fmt.Printf("  HugePages Total:        %d\n", mem.HugePagesTotal)
		fmt.Printf("  HugePages Free:         %d\n", mem.HugePagesFree)
		fmt.Printf("  HugePages Reserved:     %d\n", mem.HugePagesReserved)
		fmt.Printf("  HugePages Used:         %d\n", mem.HugePagesUsed)
		fmt.Printf("  HugePages Used Percent: %.2f%%\n", mem.HugePagesUsedPercent)
		fmt.Printf("  HugePage Size:          %d KB\n", mem.HugePageSize)

		load, err := pritunl_utils.LoadAverage()
		if err != nil {
			logger.WithFields(logger.Fields{
				"error": err,
			}).Error("imds: Failed to get load")
			utils.DelayExit(1, 1*time.Second)
			return
		}

		fmt.Println("\nLoad Average Information:")
		fmt.Printf("  CPU Units:              %d\n", load.CpuUnits)
		fmt.Printf("  Load Average (1 min):   %.2f%%\n", load.Load1)
		fmt.Printf("  Load Average (5 min):   %.2f%%\n", load.Load5)
		fmt.Printf("  Load Average (15 min):  %.2f%%\n", load.Load15)
		break
	case "version":
		fmt.Printf("pci v%s\n", constants.Version)
		break
	default:
		fmt.Printf(help)
	}

	return
}

func daemonFork() (err error) {
	fmt.Println("pritunl-cloud-agent: Forking daemon process")

	app, err := os.Executable()
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "agent: Failed to get executable path"),
		}
		return
	}

	args := []string{app}
	args = append(args, flag.Args()...)

	devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0)
	if err != nil {
		err = &errortypes.WriteError{
			errors.Wrap(err, "agent: Failed to open /dev/null"),
		}
		return
	}

	_, err = os.StartProcess(app, args, &os.ProcAttr{
		Files: []*os.File{nil, devNull, devNull},
		Sys: &syscall.SysProcAttr{
			Setsid: true,
		},
	})
	if err != nil {
		devNull.Close()
		err = &errortypes.ExecError{
			errors.Wrap(err, "agent: Failed to fork agent process"),
		}
		return
	}

	os.Exit(0)
	return
}


================================================
FILE: agent/constants/constants.go
================================================
package constants

const (
	Version      = "1.0.3248.95"
	ImdsConfPath = "/etc/pritunl-imds.json"
	ImdsLogPath  = "/var/log/pritunl-imds.log"
)


================================================
FILE: agent/imds/imds.go
================================================
package imds

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"runtime/debug"
	"strings"
	"sync"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/agent/constants"
	"github.com/pritunl/pritunl-cloud/agent/logging"
	"github.com/pritunl/pritunl-cloud/engine"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/imds/types"
	"github.com/pritunl/pritunl-cloud/telemetry"
	"github.com/pritunl/pritunl-cloud/utils"
	"github.com/pritunl/tools/logger"
	"github.com/pritunl/tools/set"
)

var (
	client = &http.Client{
		Timeout: 10 * time.Second,
	}
	curSyncHash uint32
)

type Imds struct {
	Address     string              `json:"address"`
	Port        int                 `json:"port"`
	Secret      string              `json:"secret"`
	State       string              `json:"state"`
	engine      *engine.Engine      `json:"-"`
	initialized bool                `json:"-"`
	waiter      sync.WaitGroup      `json:"-"`
	journals    map[string]*Journal `json:"-"`
	syncLock    sync.Mutex          `json:"-"`
	logger      *logging.Redirect   `json:"-"`
}

func (m *Imds) NewRequest(method, pth string, data interface{}) (
	req *http.Request, err error) {

	u := &url.URL{}
	u.Scheme = "http"
	u.Host = fmt.Sprintf("%s:%d", m.Address, m.Port)
	u.Path = pth

	var body io.Reader
	if data != nil {
		reqDataBuf := &bytes.Buffer{}
		err = json.NewEncoder(reqDataBuf).Encode(data)
		if err != nil {
			err = &errortypes.ParseError{
				errors.Wrap(err, "agent: Failed to parse request data"),
			}
			return
		}

		body = reqDataBuf
	}

	req, err = http.NewRequest(method, u.String(), body)
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "agent: Failed to create imds request"),
		}
		return
	}

	req.Header.Set("User-Agent", "pritunl-imds")
	req.Header.Set("Auth-Token", m.Secret)
	if data != nil {
		req.Header.Set("Content-Type", "application/json")
	}

	return
}

func (m *Imds) Get(query string) (val string, err error) {
	query = strings.TrimPrefix(query, "+")

	req, err := m.NewRequest("GET", "/query"+query, nil)

	resp, e := client.Do(req)
	if e != nil {
		err = &errortypes.RequestError{
			errors.Wrap(e, "agent: Imds request failed"),
		}
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		body := ""
		data, _ := ioutil.ReadAll(resp.Body)
		if data != nil {
			body = string(data)
		}

		errData := &errortypes.ErrorData{}
		err = json.Unmarshal(data, errData)
		if err != nil || errData.Error == "" {
			errData = nil
		}

		if errData != nil && errData.Message != "" {
			body = errData.Message
		}

		err = &errortypes.RequestError{
			errors.Newf(
				"agent: Imds server get error %d - %s",
				resp.StatusCode, body),
		}
		return
	}

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "agent: Imds failed to read body"),
		}
		return
	}

	val = string(data)

	return
}

type SyncResp struct {
	Spec     string           `json:"spec"`
	Hash     uint32           `json:"hash"`
	Journals []*types.Journal `json:"journals"`
}

func (m *Imds) SyncReady(timeout time.Duration) (err error) {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	ticker := time.NewTicker(200 * time.Millisecond)
	defer ticker.Stop()

	var lastErr error
	for {
		select {
		case <-ctx.Done():
			if lastErr != nil {
				err = lastErr
			} else {
				err = &errortypes.RequestError{
					errors.New("agent: Initial config timeout"),
				}
			}
			return
		case <-ticker.C:
			ready, e := m.Sync()
			if e != nil {
				lastErr = e
				continue
			}
			if !ready {
				continue
			}
			return nil
		}
	}
}

func (m *Imds) Sync() (ready bool, err error) {
	m.syncLock.Lock()
	defer m.syncLock.Unlock()

	data, err := m.GetState(curSyncHash)
	if err != nil {
		return
	}

	if m.logger != nil {
		data.Output = m.logger.GetOutput()
	}

	if m.journals != nil {
		journals := map[string][]*types.Entry{}
		for _, jrnl := range m.journals {
			journals[jrnl.Key] = jrnl.Handler.GetOutput()
		}
		if len(journals) > 0 {
			data.Journals = journals
		}
	} else {
		m.journals = map[string]*Journal{}
	}

	req, err := m.NewRequest("PUT", "/sync", data)
	if err != nil {
		return
	}

	resp, err := client.Do(req)
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "agent: Imds request failed"),
		}
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		body := ""
		data, _ := ioutil.ReadAll(resp.Body)
		if data != nil {
			body = string(data)
		}

		errData := &errortypes.ErrorData{}
		err = json.Unmarshal(data, errData)
		if err != nil || errData.Error == "" {
			errData = nil
		}

		if errData != nil && errData.Message != "" {
			body = errData.Message
		}

		err = &errortypes.RequestError{
			errors.Newf("agent: Imds server sync error %d - %s",
				resp.StatusCode, body),
		}
		return
	}

	respData := &SyncResp{}
	err = json.NewDecoder(resp.Body).Decode(respData)
	if err != nil {
		err = &errortypes.RequestError{
			errors.Wrap(err, "agent: Failed to decode imds sync resp"),
		}
		return
	}

	ready = true
	if respData.Hash == 0 {
		ready = false
	} else if curSyncHash == 0 {
		curSyncHash = respData.Hash
	} else if respData.Hash != curSyncHash && respData.Spec != "" &&
		m.engine != nil && m.initialized {

		curSyncHash = respData.Hash

		logger.WithFields(logger.Fields{
			"spec_len": len(respData.Spec),
			"hash":     int(respData.Hash),
		}).Info("agent: Queuing engine reload")

		m.engine.Queue(respData.Spec)
	}

	activeJournals := set.NewSet()
	for unit := range m.journals {
		activeJournals.Add(unit)
	}

	for _, jrnlConf := range respData.Journals {
		if activeJournals.Contains(jrnlConf.Key) {
			activeJournals.Remove(jrnlConf.Key)
			jrnl := m.journals[jrnlConf.Key]
			if jrnl != nil {
				if jrnl.Index != jrnlConf.Index ||
					jrnl.Key != jrnlConf.Key ||
					jrnl.Type != jrnlConf.Type ||
					jrnl.Unit != jrnlConf.Unit ||
					jrnl.Path != jrnlConf.Path {

					jrnl.Close()
					delete(m.journals, jrnlConf.Key)
				} else {
					continue
				}
			}
		}

		jrnl := &Journal{
			Index: jrnlConf.Index,
			Key:   jrnlConf.Key,
			Type:  jrnlConf.Type,
			Unit:  jrnlConf.Unit,
			Path:  jrnlConf.Path,
		}

		if jrnl.Type == "file" {
			jrnl.Handler = logging.NewFile(jrnlConf.Path)
		} else if jrnl.Type == "systemd" {
			jrnl.Handler = logging.NewSystemd(jrnlConf.Unit)
		} else {
			continue
		}

		err = jrnl.Open()
		if err != nil {
			return
		}

		m.journals[jrnlConf.Key] = jrnl
	}

	for jrnlKeyInf := range activeJournals.Iter() {
		jrnlKey := jrnlKeyInf.(string)
		jrnl := m.journals[jrnlKey]
		if jrnl != nil {
			jrnl.Close()
			delete(m.journals, jrnlKey)
		}
	}

	return
}

func (m *Imds) SetInitialized() {
	m.initialized = true
	if m.engine != nil {
		m.engine.StartRunner()
	}
}

func (m *Imds) RunSync(fast bool) {
	m.waiter.Add(1)

	go func() {
		defer func() {
			panc := recover()
			if panc != nil {
				logger.WithFields(logger.Fields{
					"trace": string(debug.Stack()),
					"panic": panc,
				}).Error("sync: Panic in telemetry")
			}
		}()

		for {
			telemetry.Refresh()
			time.Sleep(1 * time.Minute)
		}
	}()

	go func() {
		defer m.waiter.Done()

		for {
			func() {
				defer func() {
					panc := recover()
					if panc != nil {
						logger.WithFields(logger.Fields{
							"trace": string(debug.Stack()),
							"panic": panc,
						}).Error("agent: Panic in sync")
						time.Sleep(3 * time.Second)
						os.Exit(1)
					}
				}()

				_, err := m.Sync()
				if err != nil {
					logger.WithFields(logger.Fields{
						"error": err,
					}).Error("agent: Failed to sync")
				}
			}()

			if fast {
				time.Sleep(500 * time.Millisecond)
			} else {
				time.Sleep(1 * time.Second)
			}
		}
	}()
}

func (m *Imds) SyncStatus(status string) (err error) {
	SetStatus(status)

	_, err = m.Sync()
	if err != nil {
		logger.WithFields(logger.Fields{
			"status": status,
			"error":  err,
		}).Error("agent: Failed to sync status")
	}

	return
}

func (m *Imds) Wait() (err error) {
	m.waiter.Wait()

	return
}

func (m *Imds) Init(eng *engine.Engine) (err error) {
	m.engine = eng

	confData, err := utils.Read(constants.ImdsConfPath)
	if err != nil {
		return
	}

	err = json.Unmarshal([]byte(confData), m)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "agent: Failed to unmarshal imds conf"),
		}
		return
	}

	return
}

func (m *Imds) OpenLog() (err error) {
	m.logger = &logging.Redirect{}

	err = m.logger.Open()
	if err != nil {
		return
	}

	return
}

func (m *Imds) Close() {
	if m.logger != nil {
		m.logger.Close()
	}
}


================================================
FILE: agent/imds/journal.go
================================================
package imds

import (
	"github.com/pritunl/pritunl-cloud/agent/logging"
	"github.com/pritunl/tools/logger"
)

type Journal struct {
	Index   int32           `json:"-"`
	Key     string          `json:"-"`
	Type    string          `json:"-"`
	Unit    string          `json:"-"`
	Path    string          `json:"-"`
	Handler logging.Handler `json:"-"`
}

func (j *Journal) Open() (err error) {
	logger.WithFields(logger.Fields{
		"index": j.Index,
		"key":   j.Key,
		"type":  j.Type,
		"unit":  j.Unit,
		"path":  j.Path,
	}).Info("agent: Starting journal")

	err = j.Handler.Open()
	if err != nil {
		return
	}

	return
}

func (j *Journal) Close() {
	logger.WithFields(logger.Fields{
		"index": j.Index,
		"key":   j.Key,
		"type":  j.Type,
		"unit":  j.Unit,
		"path":  j.Path,
	}).Info("agent: Stopping journal")

	err := j.Handler.Close()
	if err != nil {
		logger.WithFields(logger.Fields{
			"index": j.Index,
			"key":   j.Key,
			"type":  j.Type,
			"unit":  j.Unit,
			"path":  j.Path,
			"error": err,
		}).Error("agent: Error stopping journal")
	}

	return
}


================================================
FILE: agent/imds/sync.go
================================================
package imds

import (
	"sync"
	"time"

	"github.com/pritunl/pritunl-cloud/imds/types"
	"github.com/pritunl/pritunl-cloud/telemetry"
	"github.com/pritunl/pritunl-cloud/utils"
	"github.com/pritunl/tools/logger"
)

var (
	curStatus     = types.Initializing
	curStatusLock sync.Mutex
)

type StateData struct {
	*types.State
}

func (m *Imds) GetState(curHash uint32) (data *StateData, err error) {
	data = &StateData{
		&types.State{},
	}

	data.Hash = curHash
	curStatusLock.Lock()
	data.Status = curStatus
	curStatusLock.Unlock()

	mem, err := utils.GetMemInfo()
	if err != nil {
		logger.WithFields(logger.Fields{
			"error": err,
		}).Limit(30 * time.Minute).Error("imds: Failed to get memory")
	} else {
		data.Memory = utils.ToFixed(mem.UsedPercent, 2)
		data.HugePages = utils.ToFixed(mem.HugePagesUsedPercent, 2)
	}

	load, err := utils.LoadAverage()
	if err != nil {
		logger.WithFields(logger.Fields{
			"error": err,
		}).Limit(30 * time.Minute).Error("imds: Failed to get load")
	} else {
		data.Load1 = load.Load1
		data.Load5 = load.Load5
		data.Load15 = load.Load15
	}

	updates, ok := telemetry.Updates.Get()
	if ok {
		data.Updates = updates
	} else {
		data.Updates = nil
	}

	return
}

func SetStatus(status string) {
	curStatusLock.Lock()
	curStatus = status
	curStatusLock.Unlock()
}


================================================
FILE: agent/imds/utils.go
================================================
package imds

import (
	"encoding/json"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/agent/constants"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/utils"
)

func GetState() string {
	confData, err := utils.Read(constants.ImdsConfPath)
	if err != nil {
		return ""
	}

	conf := &Imds{}

	err = json.Unmarshal([]byte(confData), conf)
	if err != nil {
		return ""
	}

	return conf.State
}

func SetState(state string) (err error) {
	confData, err := utils.Read(constants.ImdsConfPath)
	if err != nil {
		return
	}

	conf := &Imds{}

	err = json.Unmarshal([]byte(confData), conf)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "agent: Failed to unmarshal imds conf"),
		}
		return
	}

	conf.State = state

	dataByt, err := json.Marshal(conf)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "agent: Failed to unmarshal imds conf"),
		}
		return
	}

	err = utils.Write(constants.ImdsConfPath, string(dataByt), 0600)
	if err != nil {
		return
	}

	return
}


================================================
FILE: agent/logging/file.go
================================================
package logging

import (
	"bufio"
	"context"
	"os/exec"
	"runtime/debug"
	"strings"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/imds/types"
	"github.com/pritunl/tools/logger"
)

type File struct {
	path   string
	output chan *types.Entry
	cmd    *exec.Cmd
	ctx    context.Context
	cancel context.CancelFunc
}

func (f *File) GetOutput() (entries []*types.Entry) {
	for {
		select {
		case entry := <-f.output:
			entries = append(entries, entry)
		default:
			return
		}
	}
}

func (f *File) followJournal() (err error) {
	defer func() {
		rec := recover()
		if rec != nil {
			logger.WithFields(logger.Fields{
				"path":  f.path,
				"panic": rec,
			}).Error("agent: File follower panic")
		}
	}()

	f.cmd = exec.CommandContext(f.ctx, "tail",
		"-F", f.path,
	)

	stdout, err := f.cmd.StdoutPipe()
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "agent: Error creating stdout pipe"),
		}
		return
	}

	err = f.cmd.Start()
	if err != nil {
		err = &errortypes.ExecError{
			errors.Wrap(err, "agent: Error starting tail"),
		}
		return
	}

	scanner := bufio.NewScanner(stdout)
	buf := make([]byte, maxCapacity)
	scanner.Buffer(buf, maxCapacity)

	for scanner.Scan() {
		select {
		case <-f.ctx.Done():
			return
		default:
		}

		line := scanner.Text()

		timestamp := time.Now()
		level := int32(5)

		if strings.Contains(strings.ToLower(line), "error") {
			level = 3
		}

		select {
		case f.output <- &types.Entry{
			Timestamp: timestamp,
			Level:     level,
			Message:   line,
		}:
		default:
		}
		continue
	}

	err = scanner.Err()
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "agent: Error reading tail"),
		}
		return
	}

	f.cmd.Wait()

	return
}

func (f *File) Open() (err error) {
	f.output = make(chan *types.Entry, 10000)
	f.ctx, f.cancel = context.WithCancel(context.Background())

	go func() {
		defer func() {
			panc := recover()
			if panc != nil {
				logger.WithFields(logger.Fields{
					"trace": string(debug.Stack()),
					"panic": panc,
				}).Error("sync: Panic in tail open")
			}
		}()

		for {
			select {
			case <-f.ctx.Done():
				return
			default:
			}

			e := f.followJournal()

			select {
			case <-f.ctx.Done():
				return
			default:
			}

			if e != nil {
				logger.WithFields(logger.Fields{
					"path":  f.path,
					"error": e,
				}).Error("agent: Journal follower error, restarting")
			} else {
				logger.WithFields(logger.Fields{
					"path": f.path,
				}).Info("agent: Journal follower exited, restarting")
			}

			select {
			case <-time.After(3 * time.Second):
			case <-f.ctx.Done():
				return
			}
		}
	}()

	return
}

func (f *File) Close() (err error) {
	defer func() {
		panc := recover()
		if panc != nil {
			logger.WithFields(logger.Fields{
				"trace": string(debug.Stack()),
				"panic": panc,
			}).Error("sync: Panic in journal close")
		}
	}()

	if f.cancel != nil {
		f.cancel()
	}

	if f.cmd != nil && f.cmd.Process != nil {
		f.cmd.Process.Kill()
	}

	if f.output != nil {
		close(f.output)
	}

	return
}

func NewFile(path string) *File {
	return &File{
		path: path,
	}
}


================================================
FILE: agent/logging/handler.go
================================================
package logging

import (
	"github.com/pritunl/pritunl-cloud/imds/types"
)

type Handler interface {
	Open() (err error)
	Close() (err error)
	GetOutput() (entries []*types.Entry)
}


================================================
FILE: agent/logging/logging.go
================================================
package logging

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/agent/constants"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/imds/types"
)

const maxCapacity = 128 * 1024

type Redirect struct {
	file         *os.File
	writer       io.Writer
	origStout    *os.File
	origStderr   *os.File
	output       chan *types.Entry
	stdoutReader *os.File
	stdoutWriter *os.File
	stderrReader *os.File
	stderrWriter *os.File
}

func (r *Redirect) GetOutput() (entries []*types.Entry) {
	for {
		select {
		case entry := <-r.output:
			entries = append(entries, entry)
		default:
			return
		}
	}
}

func (r *Redirect) handleOutput(reader *os.File, level int32) {
	scanner := bufio.NewScanner(reader)
	buf := make([]byte, maxCapacity)
	scanner.Buffer(buf, maxCapacity)

	for scanner.Scan() {
		line := scanner.Text()
		timestamp := time.Now()

		fmt.Fprintf(
			r.writer, "[%s] %s\n",
			timestamp.Format("2006-01-02 15:04:05"),
			line,
		)

		select {
		case r.output <- &types.Entry{
			Timestamp: timestamp,
			Level:     level,
			Message:   line,
		}:
		default:
		}
	}
}

func (r *Redirect) Open() (err error) {
	r.file, err = os.OpenFile(
		constants.ImdsLogPath,
		os.O_APPEND|os.O_CREATE|os.O_WRONLY,
		0600,
	)
	if err != nil {
		err = &errortypes.WriteError{
			errors.Wrap(err, "agent: Failed to create log file"),
		}
		return
	}

	r.output = make(chan *types.Entry, 10000)
	r.writer = io.MultiWriter(r.file, os.Stdout)
	r.origStout = os.Stdout
	r.origStderr = os.Stderr

	r.stdoutReader, r.stdoutWriter, err = os.Pipe()
	if err != nil {
		err = &errortypes.WriteError{
			errors.Wrap(err, "agent: Failed to create stdout pipe"),
		}
		return
	}

	r.stderrReader, r.stderrWriter, err = os.Pipe()
	if err != nil {
		err = &errortypes.WriteError{
			errors.Wrap(err, "agent: Failed to create stderr pipe"),
		}
		return
	}

	os.Stdout = r.stdoutWriter
	os.Stderr = r.stderrWriter

	go r.handleOutput(r.stdoutReader, types.Info)
	go r.handleOutput(r.stderrReader, types.Error)

	return
}

func (r *Redirect) Close() (err error) {
	os.Stdout = r.origStout
	os.Stderr = r.origStderr

	if r.stdoutWriter != nil {
		r.stdoutWriter.Close()
	}
	if r.stdoutReader != nil {
		r.stdoutReader.Close()
	}
	if r.stderrWriter != nil {
		r.stderrWriter.Close()
	}
	if r.stderrReader != nil {
		r.stderrReader.Close()
	}

	err = r.file.Close()
	if err != nil {
		err = &errortypes.WriteError{
			errors.Wrap(err, "agent: Failed to close log pipe"),
		}
		return
	}

	return
}


================================================
FILE: agent/logging/systemd.go
================================================
package logging

import (
	"bufio"
	"context"
	"encoding/json"
	"os/exec"
	"runtime/debug"
	"strconv"
	"strings"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/imds/types"
	"github.com/pritunl/tools/commander"
	"github.com/pritunl/tools/logger"
)

type Systemd struct {
	unit   string
	output chan *types.Entry
	cmd    *exec.Cmd
	ctx    context.Context
	cancel context.CancelFunc
}

type journalEntry struct {
	Message   string `json:"MESSAGE"`
	Priority  string `json:"PRIORITY"`
	Timestamp string `json:"__REALTIME_TIMESTAMP"`
}

func (s *Systemd) GetOutput() (entries []*types.Entry) {
	for {
		select {
		case entry := <-s.output:
			entries = append(entries, entry)
		default:
			return
		}
	}
}

func (s *Systemd) followJournal() (err error) {
	defer func() {
		rec := recover()
		if rec != nil {
			logger.WithFields(logger.Fields{
				"unit":  s.unit,
				"panic": rec,
			}).Error("agent: Journal follower panic")
		}
	}()

	existsTime := time.Time{}
	for {
		resp, _ := commander.Exec(&commander.Opt{
			Name: "systemctl",
			Args: []string{
				"status",
				s.unit,
			},
			PipeOut: true,
			PipeErr: true,
		})

		if resp.ExitCode != 4 {
			if existsTime.IsZero() {
				existsTime = time.Now()
			}

			if resp.ExitCode == 0 || time.Since(existsTime) > 10*time.Second {
				break
			}
		}

		time.Sleep(800 * time.Millisecond)
	}

	s.cmd = exec.CommandContext(s.ctx, "journalctl",
		"-f",
		"-b",
		"-n", "20",
		"-o", "json",
		"-u", s.unit,
	)

	stdout, err := s.cmd.StdoutPipe()
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrap(err, "agent: Error creating stdout pipe"),
		}
		return
	}

	err = s.cmd.Start()
	if err != nil {
		err = &errortypes.ExecError{
			errors.Wrap(err, "agent: Error starting journalctl"),
		}
		return
	}

	scanner := bufio.NewScanner(stdout)
	buf := make([]byte, maxCapacity)
	scanner.Buffer(buf, maxCapacity)

	for scanner.Scan() {
		select {
		case <-s.ctx.Done():
			return
		default:
		}

		line := scanner.Bytes()

		var entry journalEntry
		e := json.Unmarshal(line, &entry)
		if e != nil {
			continue
		}

		var timestamp time.Time
		ts, e := strconv.ParseInt(entry.Timestamp, 10, 64)
		if e == nil {
			timestamp = time.Unix(0, ts*1000)
		} else {
			timestamp = time.Now()
		}

		level := int32(5)
		if entry.Priority != "" {
			switch entry.Priority {
			case "0":
				level = 1
			case "1", "2":
				level = 2
			case "3":
				level = 3
			case "4":
				level = 4
			case "5", "6":
				level = 5
			case "7":
				level = 6
			}
		}

		select {
		case s.output <- &types.Entry{
			Timestamp: timestamp,
			Level:     level,
			Message:   strings.TrimSuffix(entry.Message, "\n"),
		}:
		default:
		}
	}

	err = scanner.Err()
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "agent: Error reading journal"),
		}
		return
	}

	s.cmd.Wait()

	return
}

func (s *Systemd) Open() (err error) {
	s.output = make(chan *types.Entry, 10000)
	s.ctx, s.cancel = context.WithCancel(context.Background())

	go func() {
		defer func() {
			panc := recover()
			if panc != nil {
				logger.WithFields(logger.Fields{
					"trace": string(debug.Stack()),
					"panic": panc,
				}).Error("sync: Panic in journal open")
			}
		}()

		for {
			select {
			case <-s.ctx.Done():
				return
			default:
			}

			e := s.followJournal()

			select {
			case <-s.ctx.Done():
				return
			default:
			}

			if e != nil {
				logger.WithFields(logger.Fields{
					"unit":  s.unit,
					"error": e,
				}).Error("agent: Journal follower error, restarting")
			} else {
				logger.WithFields(logger.Fields{
					"unit": s.unit,
				}).Info("agent: Journal follower exited, restarting")
			}

			select {
			case <-time.After(3 * time.Second):
			case <-s.ctx.Done():
				return
			}
		}
	}()

	return
}

func (s *Systemd) Close() (err error) {
	defer func() {
		panc := recover()
		if panc != nil {
			logger.WithFields(logger.Fields{
				"trace": string(debug.Stack()),
				"panic": panc,
			}).Error("sync: Panic in journal close")
		}
	}()

	if s.cancel != nil {
		s.cancel()
	}

	if s.cmd != nil && s.cmd.Process != nil {
		s.cmd.Process.Kill()
	}

	if s.output != nil {
		close(s.output)
	}

	return
}

func NewSystemd(unit string) *Systemd {
	return &Systemd{
		unit: unit,
	}
}


================================================
FILE: agent/utils/sanitize.go
================================================
package utils

import (
	"strings"

	"github.com/pritunl/pritunl-cloud/agent/constants"
	"github.com/pritunl/tools/commander"
)

type fileOp struct {
	cmd  string
	args []string
	path string
}

type findOp struct {
	path    string
	pattern string
	action  string
}

func Sanitize() (err error) {
	operations := []fileOp{
		{"rm", []string{"-f"}, "/var/lib/systemd/random-seed"},
		{"rm", []string{"-f"}, "/etc/machine-id"},
		{"rm", []string{"-rf"}, "/root/.cache"},
		{"shred", []string{"-u"}, "/root/.ssh/authorized_keys"},
		{"shred", []string{"-u"}, "/root/.bash_history"},
		{"shred", []string{"-u"}, "/var/log/lastlog"},
		{"shred", []string{"-u"}, "/var/log/secure"},
		{"shred", []string{"-u"}, "/var/log/utmp"},
		{"shred", []string{"-u"}, "/var/log/wtmp"},
		{"shred", []string{"-u"}, "/var/log/btmp"},
		{"shred", []string{"-u"}, "/var/log/dmesg"},
		{"shred", []string{"-u"}, "/var/log/dmesg.old"},
		{"shred", []string{"-u"}, "/var/lib/systemd/random-seed"},
	}

	findOps := []findOp{
		{"/var/tmp", "-name dnf-*", "rm -rf"},
		{"/home", "-type d -name .cache", "rm -rf"},
		{"/home", "-type f -name .bash_history", "rm -f"},
		{"/var/log", "-type f -name *.gz", "rm -f"},
		{"/var/log", "-type f -name *.[0-9]", "rm -f"},
		{"/var/log", "-type f -name *-????????", "rm -f"},
		{"/var/lib/cloud/instances", "-mindepth 1", "rm -rf"},
		{"/etc/ssh", "-type f -name *_key", "shred -u"},
		{"/etc/ssh", "-type f -name *_key.pub", "shred -u"},
		{"/var/log", "-mtime -1 -type f", "truncate -s 0"},
	}

	_, _ = commander.Exec(&commander.Opt{
		Name:    "sync",
		Args:    []string{},
		PipeOut: true,
		PipeErr: true,
	})

	for _, op := range operations {
		_, _ = commander.Exec(&commander.Opt{
			Name:    op.cmd,
			Args:    append(op.args, op.path),
			PipeOut: true,
			PipeErr: true,
		})
	}

	for _, op := range findOps {
		args := []string{op.path}
		if op.pattern != "" {
			args = append(args, strings.Split(op.pattern, " ")...)
		}
		args = append(args, "-exec")
		args = append(args, strings.Split(op.action, " ")...)
		args = append(args, "{}", ";")

		_, _ = commander.Exec(&commander.Opt{
			Name:    "find",
			Args:    args,
			PipeOut: true,
			PipeErr: true,
		})
	}

	_, _ = commander.Exec(&commander.Opt{
		Name:    "touch",
		Args:    []string{"/etc/machine-id"},
		PipeOut: true,
		PipeErr: true,
	})

	_, _ = commander.Exec(&commander.Opt{
		Name:    "sync",
		Args:    []string{},
		PipeOut: true,
		PipeErr: true,
	})

	_, _ = commander.Exec(&commander.Opt{
		Name:    "history",
		Args:    []string{"-c"},
		PipeOut: true,
		PipeErr: true,
	})

	_, _ = commander.Exec(&commander.Opt{
		Name:    "fstrim",
		Args:    []string{"-av"},
		PipeOut: true,
		PipeErr: true,
	})

	return
}

func SanitizeImds() (err error) {
	_, _ = commander.Exec(&commander.Opt{
		Name:    "shred",
		Args:    []string{"-u", constants.ImdsLogPath},
		PipeOut: true,
		PipeErr: true,
	})

	_, _ = commander.Exec(&commander.Opt{
		Name:    "shred",
		Args:    []string{"-u", constants.ImdsConfPath},
		PipeOut: true,
		PipeErr: true,
	})

	return
}


================================================
FILE: agent/utils/sys.go
================================================
package utils

import (
	"io/ioutil"
	"os"
	"time"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/errortypes"
)

func Read(path string) (data string, err error) {
	dataByt, err := ioutil.ReadFile(path)
	if err != nil {
		err = &errortypes.ReadError{
			errors.Wrapf(err, "utils: Failed to read '%s'", path),
		}
		return
	}

	data = string(dataByt)
	return
}

func DelayExit(code int, delay time.Duration) {
	time.Sleep(delay)
	os.Exit(code)
}


================================================
FILE: aggregate/block.go
================================================
package aggregate

import (
	"sync"

	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo"
	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/pritunl-cloud/block"
	"github.com/pritunl/pritunl-cloud/database"
)

type BlockPipe struct {
	block.Block `bson:",inline"`
	IpCount     int64 `bson:"ip_count"`
}

type BlocksPipe struct {
	Metadata []*Metadata  `bson:"meta"`
	Blocks   []*BlockPipe `bson:"blocks"`
}

type BlockAggregate struct {
	block.Block
	Available int64 `json:"available"`
	Capacity  int64 `json:"capacity"`
}

func GetBlockPaged(db *database.Database, query *bson.M, page,
	pageCount int64) (blocks []*BlockAggregate, count int64, err error) {

	coll := db.Blocks()
	blocks = []*BlockAggregate{}

	if pageCount == 0 {
		pageCount = 20
	}
	skip := page * pageCount

	addBlock := func(doc *BlockPipe) error {
		total, e := doc.GetIpCount()
		if e != nil {
			return e
		}

		blck := &BlockAggregate{
			Block:     doc.Block,
			Available: total - doc.IpCount,
			Capacity:  total,
		}

		blocks = append(blocks, blck)
		return nil
	}

	var cursor *mongo.Cursor
	if len(*query) == 0 {
		waiter := &sync.WaitGroup{}
		var countErr error

		waiter.Add(1)
		go func() {
			defer waiter.Done()

			count, countErr = coll.EstimatedDocumentCount(db)
			if countErr != nil {
				countErr = database.ParseError(countErr)
				return
			}
		}()

		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$skip": skip,
			},
			&bson.M{
				"$limit": pageCount,
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "blocks_ip",
					"localField":   "_id",
					"foreignField": "block",
					"as":           "ips",
				},
			},
			&bson.M{
				"$addFields": &bson.M{
					"ip_count": &bson.M{
						"$size": "$ips",
					},
				},
			},
			&bson.M{
				"$project": &bson.M{
					"ips": 0,
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		for cursor.Next(db) {
			doc := &BlockPipe{}
			err = cursor.Decode(doc)
			if err != nil {
				err = database.ParseError(err)
				return
			}

			err = addBlock(doc)
			if err != nil {
				return
			}
		}

		waiter.Wait()
		if countErr != nil {
			err = countErr
			return
		}
	} else {
		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$facet": &bson.M{
					"meta": []*bson.M{
						&bson.M{
							"$count": "count",
						},
					},
					"blocks": []*bson.M{
						&bson.M{
							"$skip": skip,
						},
						&bson.M{
							"$limit": pageCount,
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "blocks_ip",
								"localField":   "_id",
								"foreignField": "block",
								"as":           "ips",
							},
						},
						&bson.M{
							"$addFields": &bson.M{
								"ip_count": &bson.M{
									"$size": "$ips",
								},
							},
						},
						&bson.M{
							"$project": &bson.M{
								"ips": 0,
							},
						},
					},
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		if !cursor.Next(db) {
			err = &database.NotFoundError{
				errors.New("aggregate: Not found"),
			}
			return
		}

		doc := &BlocksPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		if len(doc.Metadata) > 0 {
			count = doc.Metadata[0].Count
		}

		for _, blockDoc := range doc.Blocks {
			err = addBlock(blockDoc)
			if err != nil {
				return
			}
		}
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: aggregate/deployment.go
================================================
package aggregate

import (
	"time"

	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/deployment"
	"github.com/pritunl/pritunl-cloud/image"
	"github.com/pritunl/pritunl-cloud/imds/types"
	"github.com/pritunl/pritunl-cloud/instance"
	"github.com/pritunl/pritunl-cloud/journal"
	"github.com/pritunl/pritunl-cloud/node"
	"github.com/pritunl/pritunl-cloud/spec"
	"github.com/pritunl/pritunl-cloud/unit"
	"github.com/pritunl/pritunl-cloud/zone"
)

type DeploymentPipe struct {
	Deployment   `bson:",inline"`
	SpecDocs     []*spec.Spec         `bson:"spec_docs"`
	InstanceDocs []*instance.Instance `bson:"instance_docs"`
	ZoneDocs     []*zone.Zone         `bson:"zone_docs"`
	NodeDocs     []*node.Node         `bson:"node_docs"`
	ImageDocs    []*image.Image       `bson:"image_docs"`
}

type Deployment struct {
	Id                  bson.ObjectID            `bson:"_id" json:"id"`
	Pod                 bson.ObjectID            `bson:"pod" json:"pod"`
	Unit                bson.ObjectID            `bson:"unit" json:"unit"`
	Spec                bson.ObjectID            `bson:"spec" json:"spec"`
	SpecOffset          int                      `bson:"spec_offset" json:"spec_offset"`
	SpecIndex           int                      `bson:"spec_index" json:"spec_index"`
	SpecTimestamp       time.Time                `bson:"spec_timestamp" json:"spec_timestamp"`
	Timestamp           time.Time                `bson:"timestamp" json:"timestamp"`
	Tags                []string                 `bson:"tags" json:"tags"`
	Kind                string                   `bson:"kind" json:"kind"`
	State               string                   `bson:"state" json:"state"`
	Action              string                   `bson:"action" json:"action"`
	Status              string                   `bson:"status" json:"status"`
	Node                bson.ObjectID            `bson:"node" json:"node"`
	Instance            bson.ObjectID            `bson:"instance" json:"instance"`
	InstanceData        *deployment.InstanceData `bson:"instance_data" json:"instance_data"`
	DomainData          *deployment.DomainData   `bson:"domain_data" json:"domain_data"`
	Journals            []*deployment.Journal    `bson:"journals" json:"journals"`
	ImageId             bson.ObjectID            `bson:"image_id" json:"image_id"`
	ImageName           string                   `bson:"image_name" json:"image_name"`
	ZoneName            string                   `bson:"-" json:"zone_name"`
	NodeName            string                   `bson:"-" json:"node_name"`
	InstanceName        string                   `bson:"-" json:"instance_name"`
	InstanceRoles       []string                 `bson:"-" json:"instance_roles"`
	InstanceMemory      int                      `bson:"-" json:"instance_memory"`
	InstanceProcessors  int                      `bson:"-" json:"instance_processors"`
	InstanceStatus      string                   `bson:"-" json:"instance_status"`
	InstanceUptime      string                   `bson:"-" json:"instance_uptime"`
	InstanceState       string                   `bson:"-" json:"instance_state"`
	InstanceAction      string                   `bson:"-" json:"instance_action"`
	InstanceGuestStatus string                   `bson:"-" json:"instance_guest_status"`
	InstanceTimestamp   time.Time                `bson:"-" json:"instance_timestamp"`
	InstanceHeartbeat   time.Time                `bson:"-" json:"instance_heartbeat"`
	InstanceMemoryUsage float64                  `bson:"-" json:"instance_memory_usage"`
	InstanceHugePages   float64                  `bson:"-" json:"instance_hugepages"`
	InstanceLoad1       float64                  `bson:"-" json:"instance_load1"`
	InstanceLoad5       float64                  `bson:"-" json:"instance_load5"`
	InstanceLoad15      float64                  `bson:"-" json:"instance_load15"`
}

func GetDeployments(db *database.Database, unt *unit.Unit) (
	deplys []*Deployment, err error) {

	coll := db.Deployments()
	deplys = []*Deployment{}

	cursor, err := coll.Aggregate(db, []*bson.M{
		&bson.M{
			"$match": &bson.M{
				"unit": unt.Id,
			},
		},
		&bson.M{
			"$sort": &bson.M{
				"timestamp": -1,
			},
		},
		&bson.M{
			"$lookup": &bson.M{
				"from":         "specs",
				"localField":   "spec",
				"foreignField": "_id",
				"as":           "spec_docs",
			},
		},
		&bson.M{
			"$lookup": &bson.M{
				"from":         "instances",
				"localField":   "instance",
				"foreignField": "_id",
				"as":           "instance_docs",
			},
		},
		&bson.M{
			"$lookup": &bson.M{
				"from":         "zones",
				"localField":   "zone",
				"foreignField": "_id",
				"as":           "zone_docs",
			},
		},
		&bson.M{
			"$lookup": &bson.M{
				"from":         "nodes",
				"localField":   "node",
				"foreignField": "_id",
				"as":           "node_docs",
			},
		},
		&bson.M{
			"$lookup": &bson.M{
				"from":         "images",
				"localField":   "_id",
				"foreignField": "deployment",
				"as":           "image_docs",
			},
		},
		&bson.M{
			"$project": &bson.D{
				{"_id", 1},
				{"pod", 1},
				{"unit", 1},
				{"timestamp", 1},
				{"tags", 1},
				{"spec", 1},
				{"kind", 1},
				{"state", 1},
				{"action", 1},
				{"status", 1},
				{"node", 1},
				{"instance", 1},
				{"instance_data", 1},
				{"domain_data", 1},
				{"journals", 1},
				{"spec_docs.index", 1},
				{"spec_docs.timestamp", 1},
				{"instance_docs.name", 1},
				{"instance_docs.roles", 1},
				{"instance_docs.memory", 1},
				{"instance_docs.processors", 1},
				{"instance_docs.state", 1},
				{"instance_docs.action", 1},
				{"instance_docs.timestamp", 1},
				{"instance_docs.restart", 1},
				{"instance_docs.restart_block_ip", 1},
				{"instance_docs.guest", 1},
				{"zone_docs.name", 1},
				{"node_docs.name", 1},
				{"image_docs._id", 1},
				{"image_docs.name", 1},
			},
		},
	})
	if err != nil {
		err = database.ParseError(err)
		return
	}
	defer cursor.Close(db)

	latest := true
	for cursor.Next(db) {
		doc := &DeploymentPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		deply := &doc.Deployment

		if deply.Tags == nil {
			deply.Tags = []string{}
		}
		if latest {
			latest = false
			if doc.Kind == deployment.Image {
				deply.Tags = append([]string{"latest"}, deply.Tags...)
			}
		}

		deply.Journals = append([]*deployment.Journal{
			{
				Index: journal.DeploymentAgent,
				Key:   "agent",
				Type:  "agent",
			},
		}, deply.Journals...)

		if len(doc.ZoneDocs) > 0 {
			zne := doc.ZoneDocs[0]
			deply.ZoneName = zne.Name
		}

		if len(doc.NodeDocs) > 0 {
			nde := doc.NodeDocs[0]
			deply.NodeName = nde.Name
		}

		if len(doc.SpecDocs) > 0 {
			spc := doc.SpecDocs[0]

			deply.SpecOffset = spc.Index - unt.SpecIndex
			deply.SpecIndex = spc.Index
			deply.SpecTimestamp = spc.Timestamp
		}

		if len(doc.InstanceDocs) > 0 {
			inst := doc.InstanceDocs[0]
			inst.Json(true)

			deply.InstanceName = inst.Name
			deply.InstanceRoles = inst.Roles
			deply.InstanceMemory = inst.Memory
			deply.InstanceProcessors = inst.Processors
			deply.InstanceStatus = inst.Status
			deply.InstanceUptime = inst.Uptime
			deply.InstanceState = inst.State
			deply.InstanceAction = inst.Action

			if inst.Guest != nil {
				deply.InstanceGuestStatus = inst.Guest.Status
				deply.InstanceTimestamp = inst.Guest.Timestamp
				deply.InstanceHeartbeat = inst.Guest.Heartbeat
				if inst.IsActive() {
					deply.InstanceMemoryUsage = inst.Guest.Memory
					deply.InstanceHugePages = inst.Guest.HugePages
					deply.InstanceLoad1 = inst.Guest.Load1
					deply.InstanceLoad5 = inst.Guest.Load5
					deply.InstanceLoad15 = inst.Guest.Load15
				} else {
					deply.InstanceGuestStatus = types.Offline
				}
			}
		}

		if len(doc.ImageDocs) > 0 {
			img := doc.ImageDocs[0]

			deply.ImageId = img.Id
			deply.ImageName = img.Name
		}

		deplys = append(deplys, deply)
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: aggregate/disk.go
================================================
package aggregate

import (
	"sync"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/disk"
	"github.com/pritunl/pritunl-cloud/node"
)

type DiskPipe struct {
	disk.Disk `bson:",inline"`
	ImageDocs []*node.Node `bson:"image_docs"`
}

type DisksPipe struct {
	Metadata []*Metadata `bson:"meta"`
	Disks    []*DiskPipe `bson:"disks"`
}

type DiskBackup struct {
	Image bson.ObjectID `json:"image"`
	Name  string        `json:"name"`
}

type DiskAggregate struct {
	disk.Disk
	Backups []*DiskBackup `json:"backups"`
}

func GetDiskPaged(db *database.Database, query *bson.M, page,
	pageCount int64) (disks []*DiskAggregate, count int64, err error) {

	coll := db.Disks()
	disks = []*DiskAggregate{}

	if pageCount == 0 {
		pageCount = 20
	}
	skip := page * pageCount

	addDisk := func(doc *DiskPipe) {
		backups := []*DiskBackup{}

		for _, img := range doc.ImageDocs {
			backup := &DiskBackup{
				Image: img.Id,
				Name:  img.Name,
			}

			backups = append(backups, backup)
		}

		dsk := &DiskAggregate{
			Disk:    doc.Disk,
			Backups: backups,
		}

		disks = append(disks, dsk)
	}

	var cursor *mongo.Cursor
	if len(*query) == 0 {
		waiter := &sync.WaitGroup{}
		var countErr error

		waiter.Add(1)
		go func() {
			defer waiter.Done()

			count, countErr = coll.EstimatedDocumentCount(db)
			if countErr != nil {
				countErr = database.ParseError(countErr)
				return
			}
		}()

		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$skip": skip,
			},
			&bson.M{
				"$limit": pageCount,
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "images",
					"localField":   "_id",
					"foreignField": "disk",
					"as":           "image_docs",
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		for cursor.Next(db) {
			doc := &DiskPipe{}
			err = cursor.Decode(doc)
			if err != nil {
				err = database.ParseError(err)
				return
			}

			addDisk(doc)
		}

		waiter.Wait()
		if countErr != nil {
			err = countErr
			return
		}
	} else {
		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$facet": &bson.M{
					"meta": []*bson.M{
						&bson.M{
							"$count": "count",
						},
					},
					"disks": []*bson.M{
						&bson.M{
							"$skip": skip,
						},
						&bson.M{
							"$limit": pageCount,
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "images",
								"localField":   "_id",
								"foreignField": "disk",
								"as":           "image_docs",
							},
						},
					},
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		if !cursor.Next(db) {
			err = &database.NotFoundError{
				errors.New("aggregate: Not found"),
			}
			return
		}

		doc := &DisksPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		if len(doc.Metadata) > 0 {
			count = doc.Metadata[0].Count
		}

		for _, diskDoc := range doc.Disks {
			addDisk(diskDoc)
		}
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: aggregate/domain.go
================================================
package aggregate

import (
	"sync"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/domain"
)

type Domain struct {
	domain.Domain `bson:",inline"`
	Records       []*domain.Record `bson:"records" json:"records"`
}

type DomainsPipe struct {
	Metadata []*Metadata `bson:"meta"`
	Domains  []*Domain   `bson:"domains"`
}

func GetDomainPaged(db *database.Database, query *bson.M, page,
	pageCount int64) (domains []*domain.Domain, count int64, err error) {

	coll := db.Domains()
	domains = []*domain.Domain{}

	if pageCount == 0 {
		pageCount = 20
	}
	skip := page * pageCount

	addDomain := func(domn *Domain) {
		domn.Domain.Records = domn.Records
		domn.Json()
		domains = append(domains, &domn.Domain)
	}

	var cursor *mongo.Cursor
	if len(*query) == 0 {
		waiter := &sync.WaitGroup{}
		var countErr error

		waiter.Add(1)
		go func() {
			defer waiter.Done()

			count, countErr = coll.EstimatedDocumentCount(db)
			if countErr != nil {
				countErr = database.ParseError(countErr)
				return
			}
		}()

		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$skip": skip,
			},
			&bson.M{
				"$limit": pageCount,
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "domains_records",
					"localField":   "_id",
					"foreignField": "domain",
					"as":           "records",
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		for cursor.Next(db) {
			domn := &Domain{}
			err = cursor.Decode(domn)
			if err != nil {
				err = database.ParseError(err)
				return
			}

			addDomain(domn)
		}

		waiter.Wait()
		if countErr != nil {
			err = countErr
			return
		}
	} else {
		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$facet": &bson.M{
					"meta": []*bson.M{
						&bson.M{
							"$count": "count",
						},
					},
					"domains": []*bson.M{
						&bson.M{
							"$skip": skip,
						},
						&bson.M{
							"$limit": pageCount,
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "domains_records",
								"localField":   "_id",
								"foreignField": "domain",
								"as":           "records",
							},
						},
					},
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		if !cursor.Next(db) {
			err = &database.NotFoundError{
				errors.New("aggregate: Not found"),
			}
			return
		}

		doc := &DomainsPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		if len(doc.Metadata) > 0 {
			count = doc.Metadata[0].Count
		}

		for _, domn := range doc.Domains {
			addDomain(domn)
		}
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: aggregate/instance.go
================================================
package aggregate

import (
	"fmt"
	"sort"
	"strings"
	"sync"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo"
	"github.com/pritunl/pritunl-cloud/authority"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/datacenter"
	"github.com/pritunl/pritunl-cloud/disk"
	"github.com/pritunl/pritunl-cloud/drive"
	"github.com/pritunl/pritunl-cloud/firewall"
	"github.com/pritunl/pritunl-cloud/instance"
	"github.com/pritunl/pritunl-cloud/iso"
	"github.com/pritunl/pritunl-cloud/node"
	"github.com/pritunl/pritunl-cloud/pci"
	"github.com/pritunl/pritunl-cloud/usb"
	"github.com/pritunl/pritunl-cloud/vm"
)

type InstancePipe struct {
	instance.Instance `bson:",inline"`
	NodeDocs          []*node.Node             `bson:"node_docs"`
	DatacenterDocs    []*datacenter.Datacenter `bson:"datacenter_docs"`
	DiskDocs          []*disk.Disk             `bson:"disk_docs"`
}

type InstancesPipe struct {
	Metadata  []*Metadata     `bson:"meta"`
	Instances []*InstancePipe `bson:"instances"`
}

type InstanceInfo struct {
	Node          string              `json:"node"`
	NodePublicIp  string              `json:"node_public_ip"`
	Mtu           int                 `json:"mtu"`
	Iscsi         bool                `json:"iscsi"`
	Disks         []string            `json:"disks"`
	FirewallRules map[string]string   `json:"firewall_rules"`
	Authorities   []string            `json:"authorities"`
	Isos          []*iso.Iso          `json:"isos"`
	UsbDevices    []*usb.Device       `json:"usb_devices"`
	PciDevices    []*pci.Device       `json:"pci_devices"`
	DriveDevices  []*drive.Device     `json:"drive_devices"`
	CloudSubnets  []*node.CloudSubnet `json:"cloud_subnets"`
}

type InstanceAggregate struct {
	instance.Instance
	Info *InstanceInfo `json:"info"`
}

func GetInstancePaged(db *database.Database, query *bson.M, page,
	pageCount int64) (insts []*InstanceAggregate, count int64, err error) {

	coll := db.Instances()
	insts = []*InstanceAggregate{}

	if pageCount == 0 {
		pageCount = 20
	}
	skip := page * pageCount

	firesOrg := map[bson.ObjectID]map[string][]*firewall.Firewall{}
	firesRoles := map[bson.ObjectID]set.Set{}
	authrsOrg := map[bson.ObjectID]map[string][]*authority.Authority{}
	authrsRoles := map[bson.ObjectID]set.Set{}

	addInstance := func(doc *InstancePipe) error {
		info := &InstanceInfo{
			Node:          "Unknown",
			Disks:         []string{},
			FirewallRules: map[string]string{},
			Authorities:   []string{},
			CloudSubnets:  []*node.CloudSubnet{},
		}

		var nde *node.Node
		var dc *datacenter.Datacenter

		if len(doc.NodeDocs) > 0 {
			nde = doc.NodeDocs[0]
		}

		if len(doc.DatacenterDocs) > 0 {
			dc = doc.DatacenterDocs[0]
		}

		if nde != nil {
			info.Node = nde.Name
			if len(nde.PublicIps) > 0 {
				info.NodePublicIp = nde.PublicIps[0]
			}
			info.Iscsi = nde.Iscsi

			info.Isos = nde.LocalIsos

			info.CloudSubnets = nde.GetCloudSubnetsName()

			if nde.UsbPassthrough {
				info.UsbDevices = nde.UsbDevices
			}

			if nde.PciDevices != nil {
				info.PciDevices = nde.PciDevices
			}

			if nde.InstanceDrives != nil {
				info.DriveDevices = nde.InstanceDrives
			}
		}

		if nde != nil && dc != nil {
			info.Mtu = dc.GetInstanceMtu()
		}

		for _, dsk := range doc.DiskDocs {
			info.Disks = append(
				info.Disks,
				fmt.Sprintf("%s: %s", dsk.Index, dsk.Name),
			)
		}

		fires := firesOrg[doc.Organization]
		if fires == nil {
			var e error
			fires, e = firewall.GetOrgMapRoles(db, doc.Organization)
			if e != nil {
				return e
			}

			for _, roleFires := range fires {
				for _, fire := range roleFires {
					if _, ok := firesRoles[fire.Id]; ok {
						continue
					}

					roles := set.NewSet()
					for _, role := range fire.Roles {
						roles.Add(role)
					}
					firesRoles[fire.Id] = roles
				}
			}

			firesOrg[doc.Organization] = fires
		}

		authrs := authrsOrg[doc.Organization]
		if authrs == nil {
			var e error
			authrs, e = authority.GetOrgMapRoles(db, doc.Organization)
			if e != nil {
				return e
			}

			for _, roleAuthrs := range authrs {
				for _, authr := range roleAuthrs {
					if _, ok := authrsRoles[authr.Id]; ok {
						continue
					}

					roles := set.NewSet()
					for _, role := range authr.Roles {
						roles.Add(role)
					}
					authrsRoles[authr.Id] = roles
				}
			}

			authrsOrg[doc.Organization] = authrs
		}

		curFires := set.NewSet()

		firewallRules := map[string]set.Set{}
		firewallRulesKeys := []string{}
		authrNames := set.NewSet()
		for _, role := range doc.Roles {
			roleFires := fires[role]
			for _, fire := range roleFires {
				if curFires.Contains(fire.Id) {
					continue
				}
				curFires.Add(fire.Id)

				for _, rule := range fire.Ingress {
					key := rule.Protocol
					if rule.Port != "" {
						key += ":" + rule.Port
					}

					rules := firewallRules[key]
					if rules == nil {
						rules = set.NewSet()
						firewallRules[key] = rules
						firewallRulesKeys = append(
							firewallRulesKeys,
							key,
						)
					}

					for _, sourceIp := range rule.SourceIps {
						rules.Add(sourceIp)
					}
				}
			}

			roleAuthrs := authrs[role]
			for _, authr := range roleAuthrs {
				authrNames.Add(authr.Name)
			}
		}

		if !doc.Instance.Deployment.IsZero() {
			doc.Instance.LoadVirt(nil, nil)

			specRules, _, e := firewall.GetSpecRulesSlow(
				db, doc.Instance.Node, []*instance.Instance{&doc.Instance})
			if e != nil {
				return e
			}

			instNamespace := vm.GetNamespace(doc.Instance.Id, 0)
			for namespace, rules := range specRules {
				if namespace != instNamespace {
					continue
				}

				for _, rule := range rules {
					key := rule.Protocol
					if rule.Port != "" {
						key += ":" + rule.Port
					}

					rules := firewallRules[key]
					if rules == nil {
						rules = set.NewSet()
						firewallRules[key] = rules
						firewallRulesKeys = append(
							firewallRulesKeys,
							key,
						)
					}

					for _, sourceIp := range rule.SourceIps {
						rules.Add(sourceIp)
					}
				}
			}
		}

		sort.Strings(firewallRulesKeys)
		for _, key := range firewallRulesKeys {
			rules := firewallRules[key]

			vals := []string{}
			for rule := range rules.Iter() {
				vals = append(vals, rule.(string))
			}
			sort.Strings(vals)

			info.FirewallRules[key] = strings.Join(vals, ", ")
		}

		for authr := range authrNames.Iter() {
			info.Authorities = append(info.Authorities, authr.(string))
		}
		sort.Strings(info.Authorities)

		inst := &InstanceAggregate{
			Instance: doc.Instance,
			Info:     info,
		}

		insts = append(insts, inst)
		return nil
	}

	var cursor *mongo.Cursor
	if len(*query) == 0 {
		waiter := &sync.WaitGroup{}
		var countErr error

		waiter.Add(1)
		go func() {
			defer waiter.Done()

			count, countErr = coll.EstimatedDocumentCount(db)
			if countErr != nil {
				countErr = database.ParseError(countErr)
				return
			}
		}()

		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$skip": skip,
			},
			&bson.M{
				"$limit": pageCount,
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "nodes",
					"localField":   "node",
					"foreignField": "_id",
					"as":           "node_docs",
				},
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "datacenters",
					"localField":   "datacenter",
					"foreignField": "_id",
					"as":           "datacenter_docs",
				},
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "disks",
					"localField":   "_id",
					"foreignField": "instance",
					"as":           "disk_docs",
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		for cursor.Next(db) {
			doc := &InstancePipe{}
			err = cursor.Decode(doc)
			if err != nil {
				err = database.ParseError(err)
				return
			}

			err = addInstance(doc)
			if err != nil {
				return
			}
		}

		waiter.Wait()
		if countErr != nil {
			err = countErr
			return
		}
	} else {
		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$facet": &bson.M{
					"meta": []*bson.M{
						&bson.M{
							"$count": "count",
						},
					},
					"instances": []*bson.M{
						&bson.M{
							"$skip": skip,
						},
						&bson.M{
							"$limit": pageCount,
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "nodes",
								"localField":   "node",
								"foreignField": "_id",
								"as":           "node_docs",
							},
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "datacenters",
								"localField":   "datacenter",
								"foreignField": "_id",
								"as":           "datacenter_docs",
							},
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "disks",
								"localField":   "_id",
								"foreignField": "instance",
								"as":           "disk_docs",
							},
						},
					},
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		if !cursor.Next(db) {
			err = &database.NotFoundError{
				errors.New("aggregate: Not found"),
			}
			return
		}

		doc := &InstancesPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		if len(doc.Metadata) > 0 {
			count = doc.Metadata[0].Count
		}

		for _, instDoc := range doc.Instances {
			err = addInstance(instDoc)
			if err != nil {
				return
			}
		}
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: aggregate/pod.go
================================================
package aggregate

import (
	"sort"
	"sync"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/pod"
	"github.com/pritunl/pritunl-cloud/unit"
)

func sortUnits(units []*unit.Unit) {
	sort.SliceStable(units, func(i, j int) bool {
		return units[i].Name < units[j].Name
	})
}

type PodPipe struct {
	pod.Pod  `bson:",inline"`
	UnitDocs []*unit.Unit `bson:"unit_docs"`
}

type Metadata struct {
	Count int64 `bson:"count"`
}

type PodsPipe struct {
	Metadata []*Metadata `bson:"meta"`
	Pods     []*PodPipe  `bson:"pods"`
}

type PodAggregate struct {
	pod.Pod
	Units []*unit.Unit `json:"units"`
}

func GetPod(db *database.Database, usrId bson.ObjectID, query *bson.M) (
	pd *PodAggregate, err error) {

	coll := db.Pods()

	cursor, err := coll.Aggregate(db, []*bson.M{
		&bson.M{
			"$match": query,
		},
		&bson.M{
			"$lookup": &bson.M{
				"from":         "units",
				"localField":   "_id",
				"foreignField": "pod",
				"as":           "unit_docs",
			},
		},
	})
	if err != nil {
		err = database.ParseError(err)
		return
	}
	defer cursor.Close(db)

	if !cursor.Next(db) {
		err = &database.NotFoundError{
			errors.New("aggregate: Pod not found"),
		}
		return
	}

	doc := &PodPipe{}
	err = cursor.Decode(doc)
	if err != nil {
		err = database.ParseError(err)
		return
	}

	sortUnits(doc.UnitDocs)

	pd = &PodAggregate{
		Pod:   doc.Pod,
		Units: doc.UnitDocs,
	}

	pd.Json(usrId)

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}

func GetPodsPaged(db *database.Database, usrId bson.ObjectID,
	query *bson.M, page, pageCount int64) (pods []*PodAggregate,
	count int64, err error) {

	coll := db.Pods()
	pods = []*PodAggregate{}

	if pageCount == 0 {
		pageCount = 20
	}
	skip := page * pageCount

	var cursor *mongo.Cursor
	if len(*query) == 0 {
		waiter := &sync.WaitGroup{}
		var countErr error

		waiter.Add(1)
		go func() {
			defer waiter.Done()

			count, countErr = coll.EstimatedDocumentCount(db)
			if countErr != nil {
				countErr = database.ParseError(countErr)
				return
			}
		}()

		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$skip": skip,
			},
			&bson.M{
				"$limit": pageCount,
			},
			&bson.M{
				"$lookup": &bson.M{
					"from":         "units",
					"localField":   "_id",
					"foreignField": "pod",
					"as":           "unit_docs",
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		for cursor.Next(db) {
			doc := &PodPipe{}
			err = cursor.Decode(doc)
			if err != nil {
				err = database.ParseError(err)
				return
			}

			sortUnits(doc.UnitDocs)

			pd := &PodAggregate{
				Pod:   doc.Pod,
				Units: doc.UnitDocs,
			}

			pd.Json(usrId)

			pods = append(pods, pd)
		}

		waiter.Wait()
		if countErr != nil {
			err = countErr
			return
		}
	} else {
		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$facet": &bson.M{
					"meta": []*bson.M{
						&bson.M{
							"$count": "count",
						},
					},
					"pods": []*bson.M{
						&bson.M{
							"$skip": skip,
						},
						&bson.M{
							"$limit": pageCount,
						},
						&bson.M{
							"$lookup": &bson.M{
								"from":         "units",
								"localField":   "_id",
								"foreignField": "pod",
								"as":           "unit_docs",
							},
						},
					},
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		if !cursor.Next(db) {
			err = &database.NotFoundError{
				errors.New("aggregate: Not found"),
			}
			return
		}

		doc := &PodsPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		if len(doc.Metadata) > 0 {
			count = doc.Metadata[0].Count
		}

		for _, podDoc := range doc.Pods {
			sortUnits(podDoc.UnitDocs)

			pd := &PodAggregate{
				Pod:   podDoc.Pod,
				Units: podDoc.UnitDocs,
			}

			pd.Json(usrId)

			pods = append(pods, pd)
		}
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: aggregate/shape.go
================================================
package aggregate

import (
	"sync"

	"github.com/dropbox/godropbox/errors"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/mongo-go-driver/v2/mongo"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/node"
	"github.com/pritunl/pritunl-cloud/shape"
)

type ShapePipe struct {
	shape.Shape `bson:",inline"`
	NodeDocs    []*node.Node `bson:"node_docs"`
}

type ShapesPipe struct {
	Metadata []*Metadata  `bson:"meta"`
	Shapes   []*ShapePipe `bson:"shapes"`
}

func GetShapePaged(db *database.Database, query *bson.M, page,
	pageCount int64) (shapes []*shape.Shape, count int64, err error) {

	coll := db.Shapes()
	shapes = []*shape.Shape{}

	if pageCount == 0 {
		pageCount = 20
	}
	skip := page * pageCount

	sizeQuery := &bson.M{
		"$ifNull": bson.A{
			&bson.M{
				"$setIntersection": bson.A{
					&bson.M{"$ifNull": bson.A{"$roles", bson.A{}}},
					&bson.M{"$ifNull": bson.A{"$$shape_roles", bson.A{}}},
				},
			},
			bson.A{},
		},
	}

	nodeLookup := &bson.M{
		"$lookup": &bson.M{
			"from": "nodes",
			"let": &bson.M{
				"shape_roles": "$roles",
			},
			"pipeline": []*bson.M{
				{
					"$match": &bson.M{
						"$expr": &bson.M{
							"$gt": bson.A{
								&bson.M{
									"$size": sizeQuery,
								},
								0,
							},
						},
					},
				},
			},
			"as": "node_docs",
		},
	}

	addShape := func(doc *ShapePipe) {
		shpe := &doc.Shape
		shpe.NodeCount = len(doc.NodeDocs)
		shapes = append(shapes, shpe)
	}

	var cursor *mongo.Cursor
	if len(*query) == 0 {
		waiter := &sync.WaitGroup{}
		var countErr error

		waiter.Add(1)
		go func() {
			defer waiter.Done()

			count, countErr = coll.EstimatedDocumentCount(db)
			if countErr != nil {
				countErr = database.ParseError(countErr)
				return
			}
		}()

		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$skip": skip,
			},
			&bson.M{
				"$limit": pageCount,
			},
			nodeLookup,
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		for cursor.Next(db) {
			doc := &ShapePipe{}
			err = cursor.Decode(doc)
			if err != nil {
				err = database.ParseError(err)
				return
			}

			addShape(doc)
		}

		waiter.Wait()
		if countErr != nil {
			err = countErr
			return
		}
	} else {
		cursor, err = coll.Aggregate(db, []*bson.M{
			&bson.M{
				"$match": query,
			},
			&bson.M{
				"$sort": &bson.M{
					"name": 1,
				},
			},
			&bson.M{
				"$facet": &bson.M{
					"meta": []*bson.M{
						&bson.M{
							"$count": "count",
						},
					},
					"shapes": []*bson.M{
						&bson.M{
							"$skip": skip,
						},
						&bson.M{
							"$limit": pageCount,
						},
						nodeLookup,
					},
				},
			},
		})
		if err != nil {
			err = database.ParseError(err)
			return
		}
		defer cursor.Close(db)

		if !cursor.Next(db) {
			err = &database.NotFoundError{
				errors.New("aggregate: Not found"),
			}
			return
		}

		doc := &ShapesPipe{}
		err = cursor.Decode(doc)
		if err != nil {
			err = database.ParseError(err)
			return
		}

		if len(doc.Metadata) > 0 {
			count = doc.Metadata[0].Count
		}

		for _, shapeDoc := range doc.Shapes {
			addShape(shapeDoc)
		}
	}

	err = cursor.Err()
	if err != nil {
		err = database.ParseError(err)
		return
	}

	return
}


================================================
FILE: ahandlers/alert.go
================================================
package ahandlers

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/alert"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/utils"
)

type alertData struct {
	Id           bson.ObjectID `json:"id"`
	Name         string        `json:"name"`
	Comment      string        `json:"comment"`
	Organization bson.ObjectID `json:"organization"`
	Roles        []string      `json:"roles"`
	Resource     string        `json:"resource"`
	Level        int           `json:"level"`
	Frequency    int           `json:"frequency"`
	Ignores      []string      `json:"ignores"`
	ValueInt     int           `json:"value_int"`
	ValueStr     string        `json:"value_str"`
}

type alertsData struct {
	Alerts []*alert.Alert `json:"alerts"`
	Count  int64          `json:"count"`
}

func alertPut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &alertData{}

	alertId, ok := utils.ParseObjectId(c.Param("alert_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	alrt, err := alert.Get(db, alertId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	alrt.Name = data.Name
	alrt.Comment = data.Comment
	alrt.Organization = data.Organization
	alrt.Roles = data.Roles
	alrt.Resource = data.Resource
	alrt.Level = data.Level
	alrt.Frequency = data.Frequency
	alrt.Ignores = data.Ignores
	alrt.ValueInt = data.ValueInt
	alrt.ValueStr = data.ValueStr

	fields := set.NewSet(
		"name",
		"comment",
		"organization",
		"roles",
		"resource",
		"level",
		"frequency",
		"ignores",
		"value_int",
		"value_str",
	)

	errData, err := alrt.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = alrt.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	_ = event.PublishDispatch(db, "alert.change")

	c.JSON(200, alrt)
}

func alertPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &alertData{
		Name:     "new-alert",
		Resource: alert.InstanceOffline,
		Level:    alert.Medium,
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	alrt := &alert.Alert{
		Name:         data.Name,
		Comment:      data.Comment,
		Organization: data.Organization,
		Roles:        data.Roles,
		Resource:     data.Resource,
		Level:        data.Level,
		Frequency:    data.Frequency,
		Ignores:      data.Ignores,
		ValueInt:     data.ValueInt,
		ValueStr:     data.ValueStr,
	}

	errData, err := alrt.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = alrt.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	_ = event.PublishDispatch(db, "alert.change")

	c.JSON(200, alrt)
}

func alertDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	alertId, ok := utils.ParseObjectId(c.Param("alert_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := alert.Remove(db, alertId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	_ = event.PublishDispatch(db, "alert.change")

	c.JSON(200, nil)
}

func alertsDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	dta := []bson.ObjectID{}

	err := c.Bind(&dta)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	err = alert.RemoveMulti(db, dta)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	_ = event.PublishDispatch(db, "alert.change")

	c.JSON(200, nil)
}

func alertGet(c *gin.Context) {
	if demo.IsDemo() {
		alrt := demo.Alerts[0]
		c.JSON(200, alrt)
		return
	}

	db := c.MustGet("db").(*database.Database)

	alertId, ok := utils.ParseObjectId(c.Query("id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	alrt, err := alert.Get(db, alertId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.JSON(200, alrt)
}

func alertsGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &alertsData{
			Alerts: demo.Alerts,
			Count:  int64(len(demo.Alerts)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)
	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	query := bson.M{}

	alertId, ok := utils.ParseObjectId(c.Query("id"))
	if ok {
		query["_id"] = alertId
	}

	name := strings.TrimSpace(c.Query("name"))
	if name != "" {
		query["$or"] = []*bson.M{
			&bson.M{
				"name": &bson.M{
					"$regex":   fmt.Sprintf(".*%s.*", regexp.QuoteMeta(name)),
					"$options": "i",
				},
			},
		}
	}

	role := strings.TrimSpace(c.Query("role"))
	if role != "" {
		if strings.HasPrefix(role, "~") {
			role := role[1:]
			if strings.HasPrefix(role, "!") {
				query["roles"] = &bson.M{
					"$not": &bson.M{
						"$regex": fmt.Sprintf(".*%s.*",
							regexp.QuoteMeta(role[1:])),
						"$options": "i",
					},
				}
			} else {
				query["$or"] = []*bson.M{
					&bson.M{
						"roles": &bson.M{
							"$regex": fmt.Sprintf(".*%s.*",
								regexp.QuoteMeta(role)),
							"$options": "i",
						},
					},
				}
			}
		} else {
			if strings.HasPrefix(role, "!") {
				role = strings.TrimLeft(role, "!")
				query["roles"] = &bson.M{
					"$ne": role,
				}
			} else {
				query["roles"] = role
			}
		}
	}

	organization, ok := utils.ParseObjectId(c.Query("organization"))
	if ok {
		query["organization"] = organization
	}

	comment := strings.TrimSpace(c.Query("comment"))
	if comment != "" {
		query["comment"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", comment),
			"$options": "i",
		}
	}

	alerts, count, err := alert.GetAllPaged(
		db, &query, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	dta := &alertsData{
		Alerts: alerts,
		Count:  count,
	}

	c.JSON(200, dta)
}


================================================
FILE: ahandlers/audit.go
================================================
package ahandlers

import (
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/pritunl/pritunl-cloud/audit"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/utils"
)

type auditsData struct {
	Audits []*audit.Audit `json:"audits"`
	Count  int64          `json:"count"`
}

func auditsGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &auditsData{
			Audits: demo.Audits,
			Count:  int64(len(demo.Audits)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)

	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	userId, ok := utils.ParseObjectId(c.Param("user_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	audits, count, err := audit.GetAll(db, userId, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	data := &auditsData{
		Audits: audits,
		Count:  count,
	}

	c.JSON(200, data)
}


================================================
FILE: ahandlers/auth.go
================================================
package ahandlers

import (
	"strings"

	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/audit"
	"github.com/pritunl/pritunl-cloud/auth"
	"github.com/pritunl/pritunl-cloud/authorizer"
	"github.com/pritunl/pritunl-cloud/cookie"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/device"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/node"
	"github.com/pritunl/pritunl-cloud/secondary"
	"github.com/pritunl/pritunl-cloud/session"
	"github.com/pritunl/pritunl-cloud/utils"
	"github.com/pritunl/pritunl-cloud/validator"
)

func authStateGet(c *gin.Context) {
	data := auth.GetState()

	if demo.IsDemo() {
		provider := &auth.StateProvider{
			Id:    "demo",
			Type:  "demo",
			Label: "demo",
		}
		data.Providers = append(data.Providers, provider)
	}

	c.JSON(200, data)
}

type authData struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

func authSessionPost(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	data := &authData{}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	usr, errData, err := auth.Local(db, data.Username, data.Password)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(401, errData)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminPrimaryApprove,
		audit.Fields{
			"method": "local",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	devAuth, secProviderId, errAudit, errData, err := validator.ValidateAdmin(
		db, usr, false, c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		if errAudit == nil {
			errAudit = audit.Fields{
				"error":   errData.Error,
				"message": errData.Message,
			}
		}
		errAudit["method"] = "local"

		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			errAudit,
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	if devAuth {
		deviceCount, err := device.CountSecondary(db, usr.Id)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		secType := ""
		var secProvider bson.ObjectID
		if deviceCount == 0 {
			if secProviderId.IsZero() {
				secType = secondary.AdminDeviceRegister
				secProvider = secondary.DeviceProvider
			} else {
				secType = secondary.Admin
				secProvider = secProviderId
			}
		} else {
			secType = secondary.AdminDevice
			secProvider = secondary.DeviceProvider
		}

		secd, err := secondary.New(db, usr.Id, secType, secProvider)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		data, err := secd.GetData()
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(201, data)
		return
	} else if !secProviderId.IsZero() {
		secd, err := secondary.New(db, usr.Id, secondary.Admin, secProviderId)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		data, err := secd.GetData()
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(201, data)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminLogin,
		audit.Fields{
			"method": "local",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	cook := cookie.NewAdmin(c.Writer, c.Request)

	_, err = cook.NewSession(db, c.Request, usr.Id, true, session.Admin)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.Status(200)
}

type secondaryData struct {
	Token    string `json:"token"`
	Factor   string `json:"factor"`
	Passcode string `json:"passcode"`
}

func authSecondaryPost(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	data := &secondaryData{}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	secd, err := secondary.Get(db, data.Token, secondary.Admin)
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			errData := &errortypes.ErrorData{
				Error:   "secondary_expired",
				Message: "Secondary authentication has expired",
			}
			c.JSON(401, errData)
		} else {
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	usr, err := secd.GetUser(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	errData, err := secd.Handle(db, c.Request, data.Factor, data.Passcode)
	if err != nil {
		if _, ok := err.(*secondary.IncompleteError); ok {
			c.Status(201)
		} else {
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	if errData != nil {
		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			audit.Fields{
				"method":      "secondary",
				"provider_id": secd.ProviderId,
				"error":       errData.Error,
				"message":     errData.Message,
			},
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminSecondaryApprove,
		audit.Fields{
			"provider_id": secd.ProviderId,
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	deviceAuth, _, errAudit, errData, err := validator.ValidateAdmin(
		db, usr, false, c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		if errAudit == nil {
			errAudit = audit.Fields{
				"error":   errData.Error,
				"message": errData.Message,
			}
		}
		errAudit["method"] = "secondary"
		errAudit["provider_id"] = secd.ProviderId

		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			errAudit,
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	if deviceAuth {
		deviceCount, err := device.CountSecondary(db, usr.Id)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		if deviceCount == 0 {
			secd, err := secondary.New(db, usr.Id,
				secondary.AdminDeviceRegister, secondary.DeviceProvider)
			if err != nil {
				utils.AbortWithError(c, 500, err)
				return
			}

			data, err := secd.GetData()
			if err != nil {
				utils.AbortWithError(c, 500, err)
				return
			}

			c.JSON(201, data)
			return
		}
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminLogin,
		audit.Fields{
			"method": "secondary",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	cook := cookie.NewAdmin(c.Writer, c.Request)

	_, err = cook.NewSession(db, c.Request, usr.Id, true, session.Admin)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.Status(200)
}

func logoutGet(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	authr := c.MustGet("authorizer").(*authorizer.Authorizer)

	if authr.IsValid() {
		err := authr.Remove(db)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}
	}

	usr, _ := authr.GetUser(db)
	if usr != nil {
		err := audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLogout,
			audit.Fields{},
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}
	}

	c.Redirect(302, "/login")
}

func authRequestGet(c *gin.Context) {
	auth.Request(c, auth.Admin)
}

func authCallbackGet(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	sig := c.Query("sig")
	query := strings.Split(c.Request.URL.RawQuery, "&sig=")[0]

	usr, _, errAudit, errData, err := auth.Callback(db, sig, query)
	if err != nil {
		switch err.(type) {
		case *auth.InvalidState:
			c.Redirect(302, "/")
			break
		default:
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	if errData != nil {
		if usr != nil {
			if errAudit == nil {
				errAudit = audit.Fields{
					"error":   errData.Error,
					"message": errData.Message,
				}
			}
			errAudit["method"] = "callback"

			err = audit.New(
				db,
				c.Request,
				usr.Id,
				audit.AdminLoginFailed,
				errAudit,
			)
			if err != nil {
				utils.AbortWithError(c, 500, err)
				return
			}
		}

		c.JSON(401, errData)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminPrimaryApprove,
		audit.Fields{
			"method": "callback",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	devAuth, secProviderId, errAudit, errData, err := validator.ValidateAdmin(
		db, usr, false, c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		if errAudit == nil {
			errAudit = audit.Fields{
				"error":   errData.Error,
				"message": errData.Message,
			}
		}
		errAudit["method"] = "callback"

		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			errAudit,
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	if devAuth {
		deviceCount, err := device.CountSecondary(db, usr.Id)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		secType := ""
		var secProvider bson.ObjectID
		if deviceCount == 0 {
			if secProviderId.IsZero() {
				secType = secondary.AdminDeviceRegister
				secProvider = secondary.DeviceProvider
			} else {
				secType = secondary.Admin
				secProvider = secProviderId
			}
		} else {
			secType = secondary.AdminDevice
			secProvider = secondary.DeviceProvider
		}

		secd, err := secondary.New(db, usr.Id, secType, secProvider)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		urlQuery, err := secd.GetQuery()
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.Redirect(302, "/login?"+urlQuery)
		return
	} else if !secProviderId.IsZero() {
		secd, err := secondary.New(db, usr.Id, secondary.Admin, secProviderId)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		urlQuery, err := secd.GetQuery()
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.Redirect(302, "/login?"+urlQuery)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminLogin,
		audit.Fields{
			"method": "callback",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	cook := cookie.NewAdmin(c.Writer, c.Request)

	_, err = cook.NewSession(db, c.Request, usr.Id, true, session.Admin)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.Redirect(302, "/")
}

func authWanRegisterGet(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	token := c.Query("token")

	if node.Self.WebauthnDomain == "" {
		errData := &errortypes.ErrorData{
			Error:   "webauthn_domain_unavailable",
			Message: "WebAuthn domain must be configured",
		}
		c.JSON(400, errData)
		return
	}

	secd, err := secondary.Get(db, token, secondary.AdminDeviceRegister)
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			errData := &errortypes.ErrorData{
				Error:   "secondary_expired",
				Message: "Secondary authentication has expired",
			}
			c.JSON(401, errData)
		} else {
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	usr, err := secd.GetUser(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminDeviceRegisterRequest,
		audit.Fields{},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	resp, errData, err := secd.DeviceRegisterRequest(db,
		utils.GetOrigin(c.Request))
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			audit.Fields{
				"method":  "device_register",
				"error":   errData.Error,
				"message": errData.Message,
			},
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	c.JSON(200, resp)
}

type authWanRegisterData struct {
	Token string `json:"token"`
	Name  string `json:"name"`
}

func authWanRegisterPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &authWanRegisterData{}

	body, err := utils.CopyBody(c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	err = c.Bind(data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	secd, err := secondary.Get(db, data.Token, secondary.AdminDeviceRegister)
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			errData := &errortypes.ErrorData{
				Error:   "secondary_expired",
				Message: "Secondary authentication has expired",
			}
			c.JSON(401, errData)
		} else {
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	usr, err := secd.GetUser(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	_, _, errAudit, errData, err := validator.ValidateAdmin(
		db, usr, false, c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		if errAudit == nil {
			errAudit = audit.Fields{
				"error":   errData.Error,
				"message": errData.Message,
			}
		}
		errAudit["method"] = "device_register"

		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			errAudit,
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	devc, errData, err := secd.DeviceRegisterResponse(
		db, utils.GetOrigin(c.Request), body, data.Name)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.DeviceRegisterFailed,
			audit.Fields{
				"error":   errData.Error,
				"message": errData.Message,
			},
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminDeviceRegister,
		audit.Fields{
			"device_id": devc.Id,
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "device.change")

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminLogin,
		audit.Fields{
			"method": "device_register",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	cook := cookie.NewAdmin(c.Writer, c.Request)

	_, err = cook.NewSession(db, c.Request, usr.Id, true, session.Admin)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.Status(200)
}

func authWanRequestGet(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	token := c.Query("token")

	secd, err := secondary.Get(db, token, secondary.AdminDevice)
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			errData := &errortypes.ErrorData{
				Error:   "secondary_expired",
				Message: "Secondary authentication has expired",
			}
			c.JSON(401, errData)
		} else {
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	usr, err := secd.GetUser(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	resp, errData, err := secd.DeviceRequest(
		db, utils.GetOrigin(c.Request))
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			audit.Fields{
				"method":  "device",
				"error":   errData.Error,
				"message": errData.Message,
			},
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	c.JSON(200, resp)
}

type authWanRespondData struct {
	Token string `json:"token"`
}

func authWanRespondPost(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	data := &authWanRespondData{}

	body, err := utils.CopyBody(c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	err = c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	secd, err := secondary.Get(db, data.Token, secondary.AdminDevice)
	if err != nil {
		if _, ok := err.(*database.NotFoundError); ok {
			errData := &errortypes.ErrorData{
				Error:   "secondary_expired",
				Message: "Secondary authentication has expired",
			}
			c.JSON(401, errData)
		} else {
			utils.AbortWithError(c, 500, err)
		}
		return
	}

	usr, err := secd.GetUser(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	_, secProviderId, errAudit, errData, err := validator.ValidateAdmin(
		db, usr, false, c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		if errAudit == nil {
			errAudit = audit.Fields{
				"error":   errData.Error,
				"message": errData.Message,
			}
		}
		errAudit["method"] = "device"

		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			errAudit,
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	errData, err = secd.DeviceRespond(
		db, utils.GetOrigin(c.Request), body)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		err = audit.New(
			db,
			c.Request,
			usr.Id,
			audit.AdminLoginFailed,
			audit.Fields{
				"method":  "device",
				"error":   errData.Error,
				"message": errData.Message,
			},
		)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(401, errData)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminDeviceApprove,
		audit.Fields{},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if !secProviderId.IsZero() {
		secd, err := secondary.New(db, usr.Id, secondary.Admin,
			secProviderId)
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		data, err := secd.GetData()
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(201, data)
		return
	}

	err = audit.New(
		db,
		c.Request,
		usr.Id,
		audit.AdminLogin,
		audit.Fields{
			"method": "device",
		},
	)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	cook := cookie.NewAdmin(c.Writer, c.Request)

	_, err = cook.NewSession(db, c.Request, usr.Id, true, session.Admin)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.Status(200)
}


================================================
FILE: ahandlers/authority.go
================================================
package ahandlers

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/authority"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/utils"
)

type authorityData struct {
	Id           bson.ObjectID `json:"id"`
	Name         string        `json:"name"`
	Comment      string        `json:"comment"`
	Type         string        `json:"type"`
	Organization bson.ObjectID `json:"organization"`
	Roles        []string      `json:"roles"`
	Key          string        `json:"key"`
	Principals   []string      `json:"principals"`
	Certificate  string        `json:"certificate"`
}

type authoritiesData struct {
	Authorities []*authority.Authority `json:"authorities"`
	Count       int64                  `json:"count"`
}

func authorityPut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &authorityData{}

	authorityId, ok := utils.ParseObjectId(c.Param("authority_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	authr, err := authority.Get(db, authorityId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	authr.Name = data.Name
	authr.Comment = data.Comment
	authr.Type = data.Type
	authr.Organization = data.Organization
	authr.Roles = data.Roles
	authr.Key = data.Key
	authr.Principals = data.Principals
	authr.Certificate = data.Certificate

	fields := set.NewSet(
		"name",
		"comment",
		"type",
		"organization",
		"roles",
		"key",
		"principals",
		"certificate",
	)

	errData, err := authr.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = authr.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "authority.change")

	c.JSON(200, authr)
}

func authorityPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &authorityData{
		Name: "new-authority",
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	authr := &authority.Authority{
		Name:         data.Name,
		Comment:      data.Comment,
		Type:         data.Type,
		Organization: data.Organization,
		Roles:        data.Roles,
		Key:          data.Key,
		Principals:   data.Principals,
		Certificate:  data.Certificate,
	}

	errData, err := authr.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = authr.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "authority.change")

	c.JSON(200, authr)
}

func authorityDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	authorityId, ok := utils.ParseObjectId(c.Param("authority_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := authority.Remove(db, authorityId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "authority.change")

	c.JSON(200, nil)
}

func authoritiesDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := []bson.ObjectID{}

	err := c.Bind(&data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	err = authority.RemoveMulti(db, data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "authority.change")

	c.JSON(200, nil)
}

func authorityGet(c *gin.Context) {
	if demo.IsDemo() {
		authr := demo.Authorities[0]
		c.JSON(200, authr)
		return
	}

	db := c.MustGet("db").(*database.Database)

	authorityId, ok := utils.ParseObjectId(c.Param("authority_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	authr, err := authority.Get(db, authorityId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.JSON(200, authr)
}

func authoritiesGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &authoritiesData{
			Authorities: demo.Authorities,
			Count:       int64(len(demo.Authorities)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)

	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	query := bson.M{}

	authrId, ok := utils.ParseObjectId(c.Query("id"))
	if ok {
		query["_id"] = authrId
	}

	name := strings.TrimSpace(c.Query("name"))
	if name != "" {
		query["name"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", regexp.QuoteMeta(name)),
			"$options": "i",
		}
	}

	role := strings.TrimSpace(c.Query("role"))
	if role != "" {
		if strings.HasPrefix(role, "~") {
			role := role[1:]
			if strings.HasPrefix(role, "!") {
				query["roles"] = &bson.M{
					"$not": &bson.M{
						"$regex": fmt.Sprintf(".*%s.*",
							regexp.QuoteMeta(role[1:])),
						"$options": "i",
					},
				}
			} else {
				query["$or"] = []*bson.M{
					&bson.M{
						"roles": &bson.M{
							"$regex": fmt.Sprintf(".*%s.*",
								regexp.QuoteMeta(role)),
							"$options": "i",
						},
					},
				}
			}
		} else {
			if strings.HasPrefix(role, "!") {
				role = strings.TrimLeft(role, "!")
				query["roles"] = &bson.M{
					"$ne": role,
				}
			} else {
				query["roles"] = role
			}
		}
	}

	principal := strings.TrimSpace(c.Query("principal"))
	if principal != "" {
		query["principals"] = principal
	}

	organization, ok := utils.ParseObjectId(c.Query("organization"))
	if ok {
		query["organization"] = organization
	}

	comment := strings.TrimSpace(c.Query("comment"))
	if comment != "" {
		query["comment"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", comment),
			"$options": "i",
		}
	}

	authorities, count, err := authority.GetAllPaged(
		db, &query, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	data := &authoritiesData{
		Authorities: authorities,
		Count:       count,
	}

	c.JSON(200, data)
}


================================================
FILE: ahandlers/balancer.go
================================================
package ahandlers

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/balancer"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/utils"
)

type balancerData struct {
	Id           bson.ObjectID       `json:"id"`
	Name         string              `json:"name"`
	Comment      string              `json:"comment"`
	State        bool                `json:"state"`
	Type         string              `json:"type"`
	Organization bson.ObjectID       `json:"organization"`
	Datacenter   bson.ObjectID       `json:"datacenter"`
	Certificates []bson.ObjectID     `json:"certificates"`
	WebSockets   bool                `json:"websockets"`
	Domains      []*balancer.Domain  `json:"domains"`
	Backends     []*balancer.Backend `json:"backends"`
	CheckPath    string              `json:"check_path"`
}

type balancersData struct {
	Balancers []*balancer.Balancer `json:"balancers"`
	Count     int64                `json:"count"`
}

func balancerPut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &balancerData{}

	balancerId, ok := utils.ParseObjectId(c.Param("balancer_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	balnc, err := balancer.Get(db, balancerId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	balnc.Name = data.Name
	balnc.Comment = data.Comment
	balnc.State = data.State
	balnc.Type = data.Type
	balnc.Organization = data.Organization
	balnc.Datacenter = data.Datacenter
	balnc.Certificates = data.Certificates
	balnc.WebSockets = data.WebSockets
	balnc.Domains = data.Domains
	balnc.Backends = data.Backends
	balnc.CheckPath = data.CheckPath

	fields := set.NewSet(
		"name",
		"comment",
		"state",
		"type",
		"organization",
		"datacenter",
		"certificates",
		"websockets",
		"domains",
		"backends",
		"check_path",
	)

	errData, err := balnc.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = balnc.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "balancer.change")

	balnc.Json()

	c.JSON(200, balnc)
}

func balancerPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &balancerData{
		Name: "new-balancer",
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	balnc := &balancer.Balancer{
		Name:         data.Name,
		Comment:      data.Comment,
		State:        data.State,
		Type:         data.Type,
		Organization: data.Organization,
		Datacenter:   data.Datacenter,
		Certificates: data.Certificates,
		WebSockets:   data.WebSockets,
		Domains:      data.Domains,
		Backends:     data.Backends,
		CheckPath:    data.CheckPath,
	}

	errData, err := balnc.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = balnc.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "balancer.change")

	balnc.Json()

	c.JSON(200, balnc)
}

func balancerDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	balancerId, ok := utils.ParseObjectId(c.Param("balancer_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := balancer.Remove(db, balancerId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "balancer.change")

	c.JSON(200, nil)
}

func balancersDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := []bson.ObjectID{}

	err := c.Bind(&data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	err = balancer.RemoveMulti(db, data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "balancer.change")

	c.JSON(200, nil)
}

func balancerGet(c *gin.Context) {
	if demo.IsDemo() {
		balnc := demo.Balancers[0]
		c.JSON(200, balnc)
		return
	}

	db := c.MustGet("db").(*database.Database)

	balancerId, ok := utils.ParseObjectId(c.Param("balancer_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	balnc, err := balancer.Get(db, balancerId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	balnc.Json()

	c.JSON(200, balnc)
}

func balancersGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &balancersData{
			Balancers: demo.Balancers,
			Count:     int64(len(demo.Balancers)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)

	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	query := bson.M{}

	balancerId, ok := utils.ParseObjectId(c.Query("id"))
	if ok {
		query["_id"] = balancerId
	}

	name := strings.TrimSpace(c.Query("name"))
	if name != "" {
		query["name"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", regexp.QuoteMeta(name)),
			"$options": "i",
		}
	}

	organization, ok := utils.ParseObjectId(c.Query("organization"))
	if ok {
		query["organization"] = organization
	}

	datacenter, ok := utils.ParseObjectId(c.Query("datacenter"))
	if ok {
		query["datacenter"] = datacenter
	}

	comment := strings.TrimSpace(c.Query("comment"))
	if comment != "" {
		query["comment"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", comment),
			"$options": "i",
		}
	}

	balncs, count, err := balancer.GetAllPaged(db, &query, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	for _, balnc := range balncs {
		balnc.Json()
	}

	data := &balancersData{
		Balancers: balncs,
		Count:     count,
	}

	c.JSON(200, data)
}


================================================
FILE: ahandlers/block.go
================================================
package ahandlers

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/aggregate"
	"github.com/pritunl/pritunl-cloud/block"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/relations"
	"github.com/pritunl/pritunl-cloud/utils"
)

type blockData struct {
	Id       bson.ObjectID `json:"id"`
	Name     string        `json:"name"`
	Comment  string        `json:"comment"`
	Vlan     int           `json:"vlan"`
	Type     string        `json:"type"`
	Subnets  []string      `json:"subnets"`
	Subnets6 []string      `json:"subnets6"`
	Excludes []string      `json:"excludes"`
	Netmask  string        `json:"netmask"`
	Gateway  string        `json:"gateway"`
	Gateway6 string        `json:"gateway6"`
}

type blocksData struct {
	Blocks []*aggregate.BlockAggregate `json:"blocks"`
	Count  int64                       `json:"count"`
}

func blockPut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	dta := &blockData{}

	blckId, ok := utils.ParseObjectId(c.Param("block_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(dta)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	blck, err := block.Get(db, blckId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	blck.Name = dta.Name
	blck.Comment = dta.Comment
	blck.Vlan = dta.Vlan
	blck.Subnets = dta.Subnets
	blck.Subnets6 = dta.Subnets6
	blck.Excludes = dta.Excludes
	blck.Netmask = dta.Netmask
	blck.Gateway = dta.Gateway
	blck.Gateway6 = dta.Gateway6

	fields := set.NewSet(
		"name",
		"comment",
		"vlan",
		"subnets",
		"subnets6",
		"excludes",
		"netmask",
		"gateway",
		"gateway6",
	)

	errData, err := blck.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = blck.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "block.change")

	c.JSON(200, blck)
}

func blockPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	dta := &blockData{
		Name: "new-block",
	}

	err := c.Bind(dta)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	blck := &block.Block{
		Name:     dta.Name,
		Comment:  dta.Comment,
		Vlan:     dta.Vlan,
		Type:     dta.Type,
		Subnets:  dta.Subnets,
		Subnets6: dta.Subnets6,
		Excludes: dta.Excludes,
		Netmask:  dta.Netmask,
		Gateway:  dta.Gateway,
		Gateway6: dta.Gateway6,
	}

	errData, err := blck.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = blck.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "block.change")

	c.JSON(200, blck)
}

func blockDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	blckId, ok := utils.ParseObjectId(c.Param("block_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	errData, err := relations.CanDelete(db, "block", blckId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = block.Remove(db, blckId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "block.change")

	c.JSON(200, nil)
}

func blocksDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := []bson.ObjectID{}

	err := c.Bind(&data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	errData, err := relations.CanDeleteAll(db, "block", data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = block.RemoveMulti(db, data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "block.change")

	c.JSON(200, nil)
}

func blockGet(c *gin.Context) {
	if demo.IsDemo() {
		blck := demo.Blocks[0]
		c.JSON(200, blck)
		return
	}

	db := c.MustGet("db").(*database.Database)

	blckId, ok := utils.ParseObjectId(c.Param("block_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	blck, err := block.Get(db, blckId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.JSON(200, blck)
}

func blocksGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &blocksData{
			Blocks: demo.Blocks,
			Count:  int64(len(demo.Blocks)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)

	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	query := bson.M{}

	blockId, ok := utils.ParseObjectId(c.Query("id"))
	if ok {
		query["_id"] = blockId
	}

	name := strings.TrimSpace(c.Query("name"))
	if name != "" {
		query["name"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", regexp.QuoteMeta(name)),
			"$options": "i",
		}
	}

	comment := strings.TrimSpace(c.Query("comment"))
	if comment != "" {
		query["comment"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", comment),
			"$options": "i",
		}
	}

	blcks, count, err := aggregate.GetBlockPaged(db, &query, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	data := &blocksData{
		Blocks: blcks,
		Count:  count,
	}

	c.JSON(200, data)
}


================================================
FILE: ahandlers/certificate.go
================================================
package ahandlers

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/acme"
	"github.com/pritunl/pritunl-cloud/certificate"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/relations"
	"github.com/pritunl/pritunl-cloud/utils"
)

type certificateData struct {
	Id           bson.ObjectID `json:"id"`
	Name         string        `json:"name"`
	Comment      string        `json:"comment"`
	Organization bson.ObjectID `json:"organization"`
	Type         string        `json:"type"`
	Key          string        `json:"key"`
	Certificate  string        `json:"certificate"`
	AcmeDomains  []string      `json:"acme_domains"`
	AcmeType     string        `json:"acme_type"`
	AcmeAuth     string        `json:"acme_auth"`
	AcmeSecret   bson.ObjectID `json:"acme_secret"`
	Refresh      bool          `json:"refresh"`
}

type certificatesData struct {
	Certificates []*certificate.Certificate `json:"certificates"`
	Count        int64                      `json:"count"`
}

func certificatePut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &certificateData{}

	certId, ok := utils.ParseObjectId(c.Param("cert_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	cert, err := certificate.Get(db, certId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	cert.Name = data.Name
	cert.Comment = data.Comment
	cert.Organization = data.Organization
	cert.Type = data.Type
	cert.AcmeDomains = data.AcmeDomains
	cert.AcmeType = data.AcmeType
	cert.AcmeAuth = data.AcmeAuth
	cert.AcmeSecret = data.AcmeSecret

	fields := set.NewSet(
		"name",
		"comment",
		"organization",
		"type",
		"acme_domains",
		"acme_type",
		"acme_auth",
		"acme_secret",
		"info",
	)

	if cert.Type != certificate.LetsEncrypt {
		cert.Key = data.Key
		fields.Add("key")
		cert.Certificate = data.Certificate
		fields.Add("certificate")
	}

	errData, err := cert.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = cert.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if cert.Type == certificate.LetsEncrypt {
		acme.RenewBackground(cert, data.Refresh)
	}

	event.PublishDispatch(db, "certificate.change")

	c.JSON(200, cert)
}

func certificatePost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &certificateData{
		Name: "new-certificate",
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	cert := &certificate.Certificate{
		Name:         data.Name,
		Comment:      data.Comment,
		Organization: data.Organization,
		Type:         data.Type,
		AcmeDomains:  data.AcmeDomains,
		AcmeType:     data.AcmeType,
		AcmeAuth:     data.AcmeAuth,
		AcmeSecret:   data.AcmeSecret,
	}

	if cert.Type != certificate.LetsEncrypt {
		cert.Key = data.Key
		cert.Certificate = data.Certificate
	}

	errData, err := cert.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = cert.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if cert.Type == certificate.LetsEncrypt {
		acme.RenewBackground(cert, false)
	}

	event.PublishDispatch(db, "certificate.change")

	c.JSON(200, cert)
}

func certificateDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	certId, ok := utils.ParseObjectId(c.Param("cert_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	errData, err := relations.CanDelete(db, "certificate", certId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = certificate.Remove(db, certId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "certificate.change")

	c.JSON(200, nil)
}

func certificatesDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := []bson.ObjectID{}

	err := c.Bind(&data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	errData, err := relations.CanDeleteAll(db, "certificate", data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = certificate.RemoveMulti(db, data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "certificate.change")

	c.JSON(200, nil)
}

func certificateGet(c *gin.Context) {
	if demo.IsDemo() {
		cert := demo.Certificates[0]
		c.JSON(200, cert)
		return
	}

	db := c.MustGet("db").(*database.Database)

	certId, ok := utils.ParseObjectId(c.Param("cert_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	cert, err := certificate.Get(db, certId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if demo.IsDemo() {
		cert.Key = "demo"
		cert.AcmeAccount = "demo"
	}

	c.JSON(200, cert)
}

func certificatesGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &certificatesData{
			Certificates: demo.Certificates,
			Count:        int64(len(demo.Certificates)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)

	if c.Query("names") == "true" {
		certs, err := certificate.GetAllNames(db, &bson.M{})
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(200, certs)
		return
	}

	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	query := bson.M{}

	certificateId, ok := utils.ParseObjectId(c.Query("id"))
	if ok {
		query["_id"] = certificateId
	}

	name := strings.TrimSpace(c.Query("name"))
	if name != "" {
		query["name"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", regexp.QuoteMeta(name)),
			"$options": "i",
		}
	}

	organization, ok := utils.ParseObjectId(c.Query("organization"))
	if ok {
		query["organization"] = organization
	}

	comment := strings.TrimSpace(c.Query("comment"))
	if comment != "" {
		query["comment"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", comment),
			"$options": "i",
		}
	}

	certs, count, err := certificate.GetAllPaged(db, &query, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	data := &certificatesData{
		Certificates: certs,
		Count:        count,
	}

	c.JSON(200, data)
}


================================================
FILE: ahandlers/check.go
================================================
package ahandlers

import (
	"github.com/gin-gonic/gin"
)

func checkGet(c *gin.Context) {
	c.String(200, "ok")
}


================================================
FILE: ahandlers/completion.go
================================================
package ahandlers

import (
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/block"
	"github.com/pritunl/pritunl-cloud/certificate"
	"github.com/pritunl/pritunl-cloud/completion"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/datacenter"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/domain"
	"github.com/pritunl/pritunl-cloud/image"
	"github.com/pritunl/pritunl-cloud/instance"
	"github.com/pritunl/pritunl-cloud/node"
	"github.com/pritunl/pritunl-cloud/plan"
	"github.com/pritunl/pritunl-cloud/pod"
	"github.com/pritunl/pritunl-cloud/pool"
	"github.com/pritunl/pritunl-cloud/secret"
	"github.com/pritunl/pritunl-cloud/shape"
	"github.com/pritunl/pritunl-cloud/storage"
	"github.com/pritunl/pritunl-cloud/unit"
	"github.com/pritunl/pritunl-cloud/utils"
	"github.com/pritunl/pritunl-cloud/vpc"
	"github.com/pritunl/pritunl-cloud/zone"
)

func completionGet(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)

	if demo.IsDemo() {
		data := &completion.Completion{}

		for _, item := range demo.Organizations {
			data.Organizations = append(data.Organizations, &database.Named{
				Id:   item.Id,
				Name: item.Name,
			})
		}

		for _, item := range demo.Authorities {
			data.Authorities = append(data.Authorities, &database.Named{
				Id:   item.Id,
				Name: item.Name,
			})
		}

		for _, item := range demo.Policies {
			data.Policies = append(data.Policies, &database.Named{
				Id:   item.Id,
				Name: item.Name,
			})
		}

		for _, item := range demo.Domains {
			data.Domains = append(data.Domains, &domain.Completion{
				Id:           item.Id,
				Name:         item.Name,
				Organization: item.Organization,
			})
		}

		for _, item := range demo.Vpcs {
			data.Vpcs = append(data.Vpcs, &vpc.Completion{
				Id:           item.Id,
				Name:         item.Name,
				Organization: item.Organization,
				VpcId:        item.VpcId,
				Network:      item.Network,
				Subnets:      item.Subnets,
				Datacenter:   item.Datacenter,
			})
		}

		for _, item := range demo.Datacenters {
			data.Datacenters = append(data.Datacenters, &datacenter.Completion{
				Id:          item.Id,
				Name:        item.Name,
				NetworkMode: item.NetworkMode,
			})
		}

		for _, item := range demo.Blocks {
			data.Blocks = append(data.Blocks, &block.Completion{
				Id:   item.Id,
				Name: item.Name,
				Type: item.Type,
			})
		}

		for _, item := range demo.Nodes {
			data.Nodes = append(data.Nodes, &node.Completion{
				Id:    item.Id,
				Name:  item.Name,
				Zone:  item.Zone,
				Types: item.Types,
			})
		}

		for _, item := range demo.Pools {
			data.Pools = append(data.Pools, &pool.Completion{
				Id:   item.Id,
				Name: item.Name,
				Zone: item.Zone,
			})
		}

		for _, item := range demo.Zones {
			data.Zones = append(data.Zones, &zone.Completion{
				Id:         item.Id,
				Datacenter: item.Datacenter,
				Name:       item.Name,
			})
		}

		for _, item := range demo.Shapes {
			data.Shapes = append(data.Shapes, &shape.Completion{
				Id:         item.Id,
				Name:       item.Name,
				Datacenter: item.Datacenter,
				Flexible:   item.Flexible,
				Memory:     item.Memory,
				Processors: item.Processors,
			})
		}

		imgs, err := image.GetAllCompletion(db, &bson.M{})
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}
		data.Images = imgs

		for _, item := range demo.Storages {
			data.Storages = append(data.Storages, &storage.Completion{
				Id:   item.Id,
				Name: item.Name,
				Type: item.Type,
			})
		}

		for _, item := range demo.Instances {
			data.Instances = append(data.Instances, &instance.Completion{
				Id:           item.Id,
				Name:         item.Name,
				Organization: item.Organization,
				Zone:         item.Zone,
				Vpc:          item.Vpc,
				Subnet:       item.Subnet,
				Node:         item.Node,
			})
		}

		for _, item := range demo.Plans {
			data.Plans = append(data.Plans, &plan.Completion{
				Id:           item.Id,
				Name:         item.Name,
				Organization: item.Organization,
			})
		}

		for _, item := range demo.Certificates {
			data.Certificates = append(
				data.Certificates,
				&certificate.Completion{
					Id:           item.Id,
					Name:         item.Name,
					Organization: item.Organization,
					Type:         item.Type,
				},
			)
		}

		for _, item := range demo.Secrets {
			data.Secrets = append(data.Secrets, &secret.Completion{
				Id:           item.Id,
				Name:         item.Name,
				Organization: item.Organization,
				Type:         item.Type,
			})
		}

		for _, item := range demo.Pods {
			data.Pods = append(data.Pods, &pod.Completion{
				Id:           item.Id,
				Name:         item.Name,
				Organization: item.Organization,
			})
		}

		for _, item := range demo.Units {
			data.Units = append(data.Units, &unit.Completion{
				Id:           item.Id,
				Pod:          item.Pod,
				Organization: item.Organization,
				Name:         item.Name,
				Kind:         item.Kind,
			})
		}

		c.JSON(200, data)
		return
	}

	cmpl, err := completion.GetCompletion(db, bson.NilObjectID, nil)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.JSON(200, cmpl)
}


================================================
FILE: ahandlers/csrf.go
================================================
package ahandlers

import (
	"github.com/gin-gonic/gin"
	"github.com/pritunl/pritunl-cloud/authorizer"
	"github.com/pritunl/pritunl-cloud/csrf"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/utils"
)

type csrfData struct {
	Token         string `json:"token"`
	Theme         string `json:"theme"`
	EditorTheme   string `json:"editor_theme"`
	OracleLicense bool   `json:"oracle_license"`
}

func csrfGet(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)
	authr := c.MustGet("authorizer").(*authorizer.Authorizer)

	usr, err := authr.GetUser(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	token, err := csrf.NewToken(db, authr.SessionId())
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	oracleLicense := usr.OracleLicense
	if demo.IsDemo() {
		oracleLicense = true
	}

	data := &csrfData{
		Token:         token,
		Theme:         usr.Theme,
		EditorTheme:   usr.EditorTheme,
		OracleLicense: oracleLicense,
	}
	c.JSON(200, data)
}


================================================
FILE: ahandlers/datacenter.go
================================================
package ahandlers

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/datacenter"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/relations"
	"github.com/pritunl/pritunl-cloud/utils"
)

type datacenterData struct {
	Id                  bson.ObjectID   `json:"id"`
	Name                string          `json:"name"`
	Comment             string          `json:"comment"`
	NetworkMode         string          `json:"network_mode"`
	MatchOrganizations  bool            `json:"match_organizations"`
	Organizations       []bson.ObjectID `json:"organizations"`
	JumboMtu            int             `json:"jumbo_mtu"`
	PublicStorages      []bson.ObjectID `json:"public_storages"`
	PrivateStorage      bson.ObjectID   `json:"private_storage"`
	PrivateStorageClass string          `json:"private_storage_class"`
	BackupStorage       bson.ObjectID   `json:"backup_storage"`
	BackupStorageClass  string          `json:"backup_storage_class"`
}

type datacentersData struct {
	Datacenters []*datacenter.Datacenter `json:"datacenters"`
	Count       int64                    `json:"count"`
}

func datacenterPut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &datacenterData{}

	dcId, ok := utils.ParseObjectId(c.Param("dc_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	dc, err := datacenter.Get(db, dcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	dc.Name = data.Name
	dc.Comment = data.Comment
	dc.NetworkMode = data.NetworkMode
	dc.MatchOrganizations = data.MatchOrganizations
	dc.Organizations = data.Organizations
	dc.JumboMtu = data.JumboMtu
	dc.PublicStorages = data.PublicStorages
	dc.PrivateStorage = data.PrivateStorage
	dc.PrivateStorageClass = data.PrivateStorageClass
	dc.BackupStorage = data.BackupStorage
	dc.BackupStorageClass = data.BackupStorageClass

	fields := set.NewSet(
		"name",
		"comment",
		"network_mode",
		"match_organizations",
		"organizations",
		"jumbo_mtu",
		"public_storages",
		"private_storage",
		"private_storage_class",
		"backup_storage",
		"backup_storage_class",
	)

	errData, err := dc.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = dc.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "datacenter.change")

	c.JSON(200, dc)
}

func datacenterPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &datacenterData{
		Name: "new-datacenter",
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	dc := &datacenter.Datacenter{
		Name:                data.Name,
		Comment:             data.Comment,
		NetworkMode:         data.NetworkMode,
		MatchOrganizations:  data.MatchOrganizations,
		Organizations:       data.Organizations,
		JumboMtu:            data.JumboMtu,
		PublicStorages:      data.PublicStorages,
		PrivateStorage:      data.PrivateStorage,
		PrivateStorageClass: data.PrivateStorageClass,
		BackupStorage:       data.BackupStorage,
		BackupStorageClass:  data.BackupStorageClass,
	}

	errData, err := dc.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = dc.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "datacenter.change")

	c.JSON(200, dc)
}

func datacenterDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	dcId, ok := utils.ParseObjectId(c.Param("dc_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	errData, err := relations.CanDelete(db, "datacenter", dcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = datacenter.Remove(db, dcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "datacenter.change")

	c.JSON(200, nil)
}

func datacentersDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := []bson.ObjectID{}

	err := c.Bind(&data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	errData, err := relations.CanDeleteAll(db, "datacenter", data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = datacenter.RemoveMulti(db, data)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "datacenter.change")

	c.JSON(200, nil)
}

func datacenterGet(c *gin.Context) {
	if demo.IsDemo() {
		dc := demo.Datacenters[0]
		c.JSON(200, dc)
		return
	}

	db := c.MustGet("db").(*database.Database)

	dcId, ok := utils.ParseObjectId(c.Param("dc_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	dc, err := datacenter.Get(db, dcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.JSON(200, dc)
}

func datacentersGet(c *gin.Context) {
	if demo.IsDemo() {
		data := &datacentersData{
			Datacenters: demo.Datacenters,
			Count:       int64(len(demo.Datacenters)),
		}

		c.JSON(200, data)
		return
	}

	db := c.MustGet("db").(*database.Database)

	if c.Query("names") == "true" {
		dcs, err := datacenter.GetAllNames(db, &bson.M{})
		if err != nil {
			utils.AbortWithError(c, 500, err)
			return
		}

		c.JSON(200, dcs)
		return
	}

	page, _ := strconv.ParseInt(c.Query("page"), 10, 0)
	pageCount, _ := strconv.ParseInt(c.Query("page_count"), 10, 0)

	query := bson.M{}

	datacenterId, ok := utils.ParseObjectId(c.Query("id"))
	if ok {
		query["_id"] = datacenterId
	}

	name := strings.TrimSpace(c.Query("name"))
	if name != "" {
		query["name"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", regexp.QuoteMeta(name)),
			"$options": "i",
		}
	}

	organization, ok := utils.ParseObjectId(c.Query("organization"))
	if ok {
		query["organization"] = organization
	}

	comment := strings.TrimSpace(c.Query("comment"))
	if comment != "" {
		query["comment"] = &bson.M{
			"$regex":   fmt.Sprintf(".*%s.*", comment),
			"$options": "i",
		}
	}

	dc, count, err := datacenter.GetAllPaged(db, &query, page, pageCount)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	data := &datacentersData{
		Datacenters: dc,
		Count:       count,
	}

	c.JSON(200, data)
}


================================================
FILE: ahandlers/devices.go
================================================
package ahandlers

import (
	"github.com/dropbox/godropbox/container/set"
	"github.com/dropbox/godropbox/errors"
	"github.com/gin-gonic/gin"
	"github.com/pritunl/mongo-go-driver/v2/bson"
	"github.com/pritunl/pritunl-cloud/alertevent"
	"github.com/pritunl/pritunl-cloud/audit"
	"github.com/pritunl/pritunl-cloud/authorizer"
	"github.com/pritunl/pritunl-cloud/database"
	"github.com/pritunl/pritunl-cloud/demo"
	"github.com/pritunl/pritunl-cloud/device"
	"github.com/pritunl/pritunl-cloud/errortypes"
	"github.com/pritunl/pritunl-cloud/event"
	"github.com/pritunl/pritunl-cloud/node"
	"github.com/pritunl/pritunl-cloud/secondary"
	"github.com/pritunl/pritunl-cloud/utils"
)

type deviceData struct {
	User   bson.ObjectID `json:"user"`
	Name   string        `json:"name"`
	Type   string        `json:"type"`
	Mode   string        `json:"mode"`
	Number string        `json:"number"`
}

func devicePut(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &deviceData{}

	devcId, ok := utils.ParseObjectId(c.Param("device_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	devc, err := device.Get(db, devcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	devc.Name = data.Name

	fields := set.NewSet(
		"name",
	)

	errData, err := devc.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = devc.CommitFields(db, fields)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "device.change")

	c.JSON(200, devc)
}

func devicePost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &deviceData{}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	devc := device.New(data.User, data.Type, data.Mode)

	devc.Name = data.Name
	devc.Number = data.Number

	errData, err := devc.Validate(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	err = devc.Insert(db)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "device.change")

	c.JSON(200, devc)
}

func deviceDelete(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	devcId, ok := utils.ParseObjectId(c.Param("device_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := device.Remove(db, devcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "device.change")

	c.JSON(200, nil)
}

func devicesGet(c *gin.Context) {
	db := c.MustGet("db").(*database.Database)

	usrId, ok := utils.ParseObjectId(c.Param("user_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	devices, err := device.GetAllSorted(db, usrId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	c.JSON(200, devices)
}

func deviceAlertPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	data := &deviceData{}

	devcId, ok := utils.ParseObjectId(c.Param("resource_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	err := c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.AbortWithError(c, 500, err)
		return
	}

	devc, err := device.Get(db, devcId)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	errData, err := alertevent.SendTest(db, devc)
	if errData != nil {
		c.JSON(400, errData)
		return
	}

	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	event.PublishDispatch(db, "device.change")

	c.JSON(200, devc)
}

func deviceMethodPost(c *gin.Context) {
	switch c.Param("method") {
	case "alert":
		deviceAlertPost(c)
		return
	default:
		utils.AbortWithStatus(c, 404)
		return
	}

	return
}

type devicesWanRegisterRespData struct {
	Token   string      `json:"token"`
	Options interface{} `json:"options"`
}

func deviceWanRegisterGet(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)

	if node.Self.WebauthnDomain == "" {
		errData := &errortypes.ErrorData{
			Error:   "webauthn_domain_unavailable",
			Message: "WebAuthn domain must be configured",
		}
		c.JSON(400, errData)
		return
	}

	usrId, ok := utils.ParseObjectId(c.Param("user_id"))
	if !ok {
		utils.AbortWithStatus(c, 400)
		return
	}

	secd, err := secondary.New(db, usrId,
		secondary.AdminDeviceRegister, secondary.DeviceProvider)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	jsonResp, errData, err := secd.DeviceRegisterRequest(db,
		utils.GetOrigin(c.Request))
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	if errData != nil {
		c.JSON(400, errData)
		return
	}

	resp := &devicesWanRegisterRespData{
		Token:   secd.Id,
		Options: jsonResp,
	}

	c.JSON(200, resp)
}

type devicesWanRegisterData struct {
	Token string `json:"token"`
	Name  string `json:"name"`
}

func deviceWanRegisterPost(c *gin.Context) {
	if demo.Blocked(c) {
		return
	}

	db := c.MustGet("db").(*database.Database)
	authr := c.MustGet("authorizer").(*authorizer.Authorizer)
	data := &devicesWanRegisterData{}

	body, err := utils.CopyBody(c.Request)
	if err != nil {
		utils.AbortWithError(c, 500, err)
		return
	}

	err = c.Bind(data)
	if err != nil {
		err = &errortypes.ParseError{
			errors.Wrap(err, "handler: Bind error"),
		}
		utils.A
Download .txt
gitextract_pa6e1wrf/

├── .gitattributes
├── .gitignore
├── CHANGES
├── LICENSE
├── README.md
├── acme/
│   ├── acme.go
│   ├── challenge.go
│   ├── constants.go
│   └── utils.go
├── advisory/
│   ├── advisory.go
│   ├── constants.go
│   └── utils.go
├── agent/
│   ├── agent.go
│   ├── constants/
│   │   └── constants.go
│   ├── imds/
│   │   ├── imds.go
│   │   ├── journal.go
│   │   ├── sync.go
│   │   └── utils.go
│   ├── logging/
│   │   ├── file.go
│   │   ├── handler.go
│   │   ├── logging.go
│   │   └── systemd.go
│   └── utils/
│       ├── sanitize.go
│       └── sys.go
├── aggregate/
│   ├── block.go
│   ├── deployment.go
│   ├── disk.go
│   ├── domain.go
│   ├── instance.go
│   ├── pod.go
│   └── shape.go
├── ahandlers/
│   ├── alert.go
│   ├── audit.go
│   ├── auth.go
│   ├── authority.go
│   ├── balancer.go
│   ├── block.go
│   ├── certificate.go
│   ├── check.go
│   ├── completion.go
│   ├── csrf.go
│   ├── datacenter.go
│   ├── devices.go
│   ├── disk.go
│   ├── domain.go
│   ├── event.go
│   ├── firewall.go
│   ├── handlers.go
│   ├── image.go
│   ├── instance.go
│   ├── license.go
│   ├── log.go
│   ├── node.go
│   ├── organization.go
│   ├── plan.go
│   ├── pod.go
│   ├── policy.go
│   ├── pool.go
│   ├── relations.go
│   ├── secret.go
│   ├── session.go
│   ├── settings.go
│   ├── shape.go
│   ├── static.go
│   ├── storage.go
│   ├── subscription.go
│   ├── theme.go
│   ├── user.go
│   ├── vpc.go
│   └── zone.go
├── alert/
│   ├── alert.go
│   ├── constants.go
│   └── utils.go
├── alertevent/
│   ├── alertevent.go
│   └── utils.go
├── arp/
│   └── arp.go
├── audit/
│   ├── audit.go
│   ├── constants.go
│   └── utils.go
├── auth/
│   ├── auth.go
│   ├── authzero.go
│   ├── azure.go
│   ├── constants.go
│   ├── errortypes.go
│   ├── google.go
│   ├── handler.go
│   ├── jumpcloud.go
│   ├── saml.go
│   ├── state.go
│   ├── sync.go
│   └── utils.go
├── authority/
│   ├── authority.go
│   ├── constants.go
│   └── utils.go
├── authorizer/
│   ├── authorizer.go
│   ├── constants.go
│   └── utils.go
├── backup/
│   └── backup.go
├── balancer/
│   ├── balancer.go
│   ├── constants.go
│   └── utils.go
├── block/
│   ├── block.go
│   ├── constants.go
│   ├── errortypes.go
│   ├── ip.go
│   └── utils.go
├── bridges/
│   └── bridges.go
├── certificate/
│   ├── certificate.go
│   ├── constants.go
│   └── utils.go
├── cloud/
│   ├── cloud.go
│   └── oracle.go
├── cloudinit/
│   ├── cloudinit.go
│   ├── query.go
│   └── utils.go
├── cmd/
│   ├── backup.go
│   ├── dhcp.go
│   ├── imds.go
│   ├── instance.go
│   ├── log.go
│   ├── mtu.go
│   ├── node.go
│   ├── optimize.go
│   └── settings.go
├── colorize/
│   └── colorize.go
├── completion/
│   └── completion.go
├── compositor/
│   └── compositor.go
├── config/
│   └── config.go
├── constants/
│   └── constants.go
├── cookie/
│   ├── cookie.go
│   └── utils.go
├── crypto/
│   └── crypto.go
├── csrf/
│   └── csrf.go
├── data/
│   ├── disk.go
│   ├── image.go
│   ├── resize.go
│   ├── sync.go
│   └── utils.go
├── database/
│   ├── base.go
│   ├── client.go
│   ├── collection.go
│   ├── database.go
│   ├── errors.go
│   ├── index.go
│   └── utils.go
├── datacenter/
│   ├── constants.go
│   ├── datacenter.go
│   └── utils.go
├── defaults/
│   └── defaults.go
├── demo/
│   ├── alert.go
│   ├── authority.go
│   ├── balancer.go
│   ├── block.go
│   ├── certificate.go
│   ├── datacenter.go
│   ├── demo.go
│   ├── disk.go
│   ├── domain.go
│   ├── firewall.go
│   ├── instance.go
│   ├── log.go
│   ├── node.go
│   ├── organization.go
│   ├── plan.go
│   ├── pod.go
│   ├── policy.go
│   ├── pool.go
│   ├── rand.go
│   ├── secret.go
│   ├── shape.go
│   ├── storage.go
│   ├── subscription.go
│   ├── user.go
│   ├── vpc.go
│   └── zone.go
├── deploy/
│   ├── deploy.go
│   ├── deployments.go
│   ├── disks.go
│   ├── imds.go
│   ├── instances.go
│   ├── ipset.go
│   ├── iptables.go
│   ├── namespace.go
│   ├── network.go
│   └── services.go
├── deployment/
│   ├── constants.go
│   ├── deployment.go
│   └── utils.go
├── device/
│   ├── constants.go
│   ├── device.go
│   ├── facet.go
│   └── utils.go
├── dhcpc/
│   ├── constants.go
│   ├── dhcpc.go
│   ├── imds.go
│   ├── lease.go
│   ├── lease4.go
│   ├── lease6.go
│   ├── systemd.go
│   └── utils.go
├── dhcps/
│   ├── dhcp4.go
│   ├── dhcp6.go
│   ├── ndp.go
│   └── systemd.go
├── disk/
│   ├── constants.go
│   ├── disk.go
│   ├── sort.go
│   └── utils.go
├── dns/
│   ├── aws.go
│   ├── cloudflare.go
│   ├── constants.go
│   ├── dns.go
│   ├── errors.go
│   ├── google.go
│   ├── oracle.go
│   └── utils.go
├── dnss/
│   ├── constants.go
│   ├── database.go
│   ├── dnss.go
│   ├── plugin.go
│   └── response.go
├── domain/
│   ├── constants.go
│   ├── domain.go
│   ├── record.go
│   ├── sort.go
│   └── utils.go
├── drive/
│   ├── drive.go
│   └── utils.go
├── engine/
│   ├── bash.go
│   ├── constants.go
│   ├── engine.go
│   ├── parser.go
│   └── python.go
├── errortypes/
│   └── errortypes.go
├── eval/
│   ├── constants.go
│   ├── errortypes.go
│   ├── eval.go
│   └── utils.go
├── event/
│   ├── event.go
│   ├── listener.go
│   └── socket.go
├── features/
│   ├── qemu.go
│   └── systemd.go
├── finder/
│   ├── constants.go
│   └── resources.go
├── firewall/
│   ├── constants.go
│   ├── firewall.go
│   ├── spec.go
│   └── utils.go
├── geo/
│   └── geo.go
├── go.mod
├── go.sum
├── guest/
│   ├── guest.go
│   └── power.go
├── hnetwork/
│   ├── hnetwork.go
│   └── utils.go
├── hugepages/
│   └── hugepages.go
├── image/
│   ├── constants.go
│   ├── errortypes.go
│   ├── image.go
│   ├── sort.go
│   └── utils.go
├── imds/
│   ├── config.go
│   ├── imds.go
│   ├── resource/
│   │   ├── resource.go
│   │   └── utils.go
│   ├── server/
│   │   ├── config/
│   │   │   └── config.go
│   │   ├── constants/
│   │   │   └── constants.go
│   │   ├── errortypes/
│   │   │   └── errortypes.go
│   │   ├── handlers/
│   │   │   ├── certificate.go
│   │   │   ├── dhcp.go
│   │   │   ├── handlers.go
│   │   │   ├── instance.go
│   │   │   ├── node.go
│   │   │   ├── query.go
│   │   │   ├── secret.go
│   │   │   ├── sync.go
│   │   │   └── vpc.go
│   │   ├── router/
│   │   │   └── router.go
│   │   ├── server.go
│   │   ├── state/
│   │   │   └── state.go
│   │   └── utils/
│   │       ├── files.go
│   │       ├── misc.go
│   │       └── request.go
│   ├── systemd.go
│   └── types/
│       ├── certificate.go
│       ├── config.go
│       ├── constants.go
│       ├── domain.go
│       ├── instance.go
│       ├── journal.go
│       ├── node.go
│       ├── pod.go
│       ├── secret.go
│       ├── state.go
│       └── vpc.go
├── info/
│   └── instance.go
├── instance/
│   ├── constants.go
│   ├── errortypes.go
│   ├── instance.go
│   └── utils.go
├── interfaces/
│   └── interfaces.go
├── ip/
│   ├── interface.go
│   └── ip.go
├── iproute/
│   ├── address.go
│   ├── bridge.go
│   └── iface.go
├── ipset/
│   ├── names.go
│   ├── sets.go
│   ├── state.go
│   └── utils.go
├── iptables/
│   ├── iptables.go
│   ├── lock.go
│   ├── rules.go
│   ├── state.go
│   ├── update.go
│   └── utils.go
├── ipvs/
│   ├── constants.go
│   ├── ipvs.go
│   ├── service.go
│   └── target.go
├── iscsi/
│   └── iscsi.go
├── iso/
│   └── iso.go
├── journal/
│   ├── constants.go
│   ├── journal.go
│   ├── store.go
│   └── utils.go
├── lock/
│   └── lvm.go
├── log/
│   ├── constants.go
│   ├── log.go
│   └── utils.go
├── logger/
│   ├── database.go
│   ├── file.go
│   ├── formatter.go
│   ├── hook.go
│   ├── limiter.go
│   ├── logger.go
│   ├── sender.go
│   └── writer.go
├── lvm/
│   ├── lv.go
│   └── vgs.go
├── main.go
├── middlewear/
│   ├── gzip.go
│   └── middlewear.go
├── mtu/
│   └── mtu.go
├── netconf/
│   ├── address.go
│   ├── base.go
│   ├── bridge.go
│   ├── clear.go
│   ├── external.go
│   ├── host.go
│   ├── iface.go
│   ├── imds.go
│   ├── internal.go
│   ├── ip.go
│   ├── netconf.go
│   ├── nodeport.go
│   ├── oracle.go
│   ├── space.go
│   ├── utils.go
│   ├── validate.go
│   └── vlan.go
├── node/
│   ├── block.go
│   ├── certificate.go
│   ├── constants.go
│   ├── interfaces.go
│   ├── node.go
│   ├── oracle.go
│   └── utils.go
├── nodeport/
│   ├── constants.go
│   ├── mapping.go
│   ├── network.go
│   ├── nodeport.go
│   └── utils.go
├── nonce/
│   └── nonce.go
├── notification/
│   └── notification.go
├── oracle/
│   ├── iface.go
│   ├── metadata.go
│   ├── oracle.go
│   ├── provider.go
│   ├── routetable.go
│   ├── subnet.go
│   ├── utils.go
│   └── vnic.go
├── organization/
│   ├── organization.go
│   └── utils.go
├── paths/
│   ├── paths.go
│   └── utils.go
├── pci/
│   ├── pci.go
│   └── utils.go
├── permission/
│   ├── permission.go
│   └── user.go
├── plan/
│   ├── constants.go
│   ├── data.go
│   ├── plan.go
│   └── utils.go
├── planner/
│   ├── planner.go
│   └── utils.go
├── pod/
│   ├── pod.go
│   └── utils.go
├── policy/
│   ├── constants.go
│   ├── policy.go
│   └── utils.go
├── pool/
│   ├── constants.go
│   ├── pool.go
│   └── utils.go
├── proxy/
│   ├── constants.go
│   ├── domain.go
│   ├── errortypes.go
│   ├── proxy.go
│   ├── resolver.go
│   ├── reverse.go
│   ├── transport.go
│   ├── types.go
│   ├── utils.go
│   └── ws.go
├── qemu/
│   ├── constants.go
│   ├── data.go
│   ├── disk.go
│   ├── manage.go
│   ├── network.go
│   ├── power.go
│   ├── qemu.go
│   ├── routes.go
│   ├── sort.go
│   ├── usb.go
│   └── utils.go
├── qga/
│   └── qga.go
├── qmp/
│   ├── backup.go
│   ├── disk.go
│   ├── errors.go
│   ├── password.go
│   ├── power.go
│   ├── qmp.go
│   └── vnc.go
├── qms/
│   ├── disk.go
│   ├── power.go
│   ├── qms.go
│   ├── usb.go
│   ├── utils.go
│   └── vnc.go
├── redirect/
│   ├── acme.go
│   ├── crypto/
│   │   └── crypto.go
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
│   └── utils.go
├── relations/
│   ├── definitions/
│   │   ├── block.go
│   │   ├── certificate.go
│   │   ├── datacenter.go
│   │   ├── definitions.go
│   │   ├── firewall.go
│   │   ├── instance.go
│   │   ├── node.go
│   │   ├── organization.go
│   │   ├── pod.go
│   │   ├── policy.go
│   │   ├── secret.go
│   │   ├── shape.go
│   │   ├── vpc.go
│   │   └── zone.go
│   ├── registry.go
│   ├── relations.go
│   ├── response.go
│   └── utils.go
├── render/
│   ├── constants.go
│   └── render.go
├── requires/
│   ├── errors.go
│   └── requires.go
├── rokey/
│   ├── cache.go
│   ├── rokey.go
│   └── utils.go
├── router/
│   ├── certificates.go
│   ├── constants.go
│   └── router.go
├── scheduler/
│   ├── constants.go
│   ├── scheduler.go
│   ├── unit.go
│   └── utils.go
├── secondary/
│   ├── constants.go
│   ├── duo.go
│   ├── errors.go
│   ├── okta.go
│   ├── onelogin.go
│   ├── secondary.go
│   └── utils.go
├── secret/
│   ├── constants.go
│   ├── oracle.go
│   ├── secret.go
│   └── utils.go
├── session/
│   ├── constants.go
│   ├── session.go
│   └── utils.go
├── settings/
│   ├── acme.go
│   ├── auth.go
│   ├── hypervisor.go
│   ├── local.go
│   ├── registry.go
│   ├── router.go
│   ├── settings.go
│   ├── system.go
│   └── telemetry.go
├── setup/
│   └── iptables.go
├── shape/
│   ├── constants.go
│   ├── node.go
│   ├── shape.go
│   └── utils.go
├── signature/
│   ├── signature.go
│   └── utils.go
├── spec/
│   ├── constants.go
│   ├── domain.go
│   ├── firewall.go
│   ├── instance.go
│   ├── journal.go
│   ├── node.go
│   ├── spec.go
│   └── utils.go
├── state/
│   ├── arps.go
│   ├── authorities.go
│   ├── authorities_preload.go
│   ├── datacenter.go
│   ├── deployments.go
│   ├── disks.go
│   ├── domains.go
│   ├── firewalls.go
│   ├── firewalls_preload.go
│   ├── instances.go
│   ├── instances_preload.go
│   ├── network.go
│   ├── package.go
│   ├── pools.go
│   ├── runtimes.go
│   ├── schedulers.go
│   ├── state.go
│   ├── state_old.go
│   ├── virtuals.go
│   ├── vpcs.go
│   ├── zone.go
│   └── zones.go
├── static/
│   ├── file.go
│   └── static.go
├── storage/
│   ├── constants.go
│   ├── storage.go
│   └── utils.go
├── store/
│   ├── address.go
│   ├── arp.go
│   ├── disks.go
│   ├── routes.go
│   ├── usb.go
│   └── virt.go
├── subscription/
│   └── subscription.go
├── sync/
│   ├── auth.go
│   ├── nodes.go
│   ├── sync.go
│   └── vm.go
├── systemd/
│   ├── systemd.go
│   └── utils.go
├── task/
│   ├── acme.go
│   ├── advisory.go
│   ├── backing.go
│   ├── balancer.go
│   ├── blocks.go
│   ├── cache.go
│   ├── constants.go
│   ├── deployments.go
│   ├── domains.go
│   ├── imds.go
│   ├── job.go
│   ├── notification.go
│   ├── scheduler.go
│   ├── spec.go
│   ├── specindex.go
│   ├── storage.go
│   └── task.go
├── telemetry/
│   ├── constants.go
│   ├── telemetry.go
│   ├── updates.go
│   └── utils.go
├── tools/
│   ├── autoindex.py
│   ├── build_run.sh
│   ├── builder.py
│   ├── generate_demo_data.py
│   ├── generate_files.py
│   ├── package/
│   │   ├── PKGBUILD
│   │   └── README.md
│   ├── pritunl-cloud-redirect.service
│   ├── pritunl-cloud-redirect.socket
│   ├── pritunl-cloud.service
│   ├── tsc_run.sh
│   ├── virt-install/
│   │   ├── README.md
│   │   ├── download.sh
│   │   ├── install/
│   │   │   ├── almalinux10.sh
│   │   │   ├── almalinux8.sh
│   │   │   ├── almalinux9.sh
│   │   │   ├── alpinelinux.sh
│   │   │   ├── archlinux.sh
│   │   │   ├── fedora43.sh
│   │   │   ├── fedora44.sh
│   │   │   ├── freebsd.sh
│   │   │   ├── oraclelinux10.sh
│   │   │   ├── oraclelinux7.sh
│   │   │   ├── oraclelinux8.sh
│   │   │   ├── oraclelinux9.sh
│   │   │   ├── rockylinux10.sh
│   │   │   ├── rockylinux8.sh
│   │   │   ├── rockylinux9.sh
│   │   │   ├── ubuntu24.sh
│   │   │   └── ubuntu26.sh
│   │   └── setup/
│   │       ├── alpine.sh
│   │       ├── arch.sh
│   │       ├── debian.sh
│   │       ├── fedora.sh
│   │       ├── freebsd.sh
│   │       ├── rhel10.sh
│   │       ├── rhel7.sh
│   │       ├── rhel8.sh
│   │       └── rhel9.sh
│   └── webpack_run.sh
├── tpm/
│   ├── tpm.go
│   └── utils.go
├── twilio/
│   ├── twilio.go
│   └── utils.go
├── uhandlers/
│   ├── alert.go
│   ├── auth.go
│   ├── authority.go
│   ├── balancer.go
│   ├── certificate.go
│   ├── check.go
│   ├── completion.go
│   ├── csrf.go
│   ├── datacenter.go
│   ├── devices.go
│   ├── disk.go
│   ├── domain.go
│   ├── event.go
│   ├── firewall.go
│   ├── handlers.go
│   ├── image.go
│   ├── instance.go
│   ├── license.go
│   ├── node.go
│   ├── organization.go
│   ├── plan.go
│   ├── pod.go
│   ├── pool.go
│   ├── relations.go
│   ├── secret.go
│   ├── shape.go
│   ├── static.go
│   ├── theme.go
│   ├── utils.go
│   ├── vpc.go
│   └── zone.go
├── unit/
│   ├── unit.go
│   └── utils.go
├── upgrade/
│   ├── created.go
│   ├── instance.go
│   ├── journal.go
│   ├── node.go
│   ├── objectid.go
│   ├── roles.go
│   ├── state.go
│   ├── upgrade.go
│   └── zone_datacenter.go
├── usb/
│   ├── usb.go
│   └── utils.go
├── user/
│   ├── constants.go
│   ├── user.go
│   └── utils.go
├── useragent/
│   └── useragent.go
├── utils/
│   ├── crypto.go
│   ├── dns.go
│   ├── files.go
│   ├── filter.go
│   ├── limiter.go
│   ├── math.go
│   ├── misc.go
│   ├── multilock.go
│   ├── multitimeoutlock.go
│   ├── network.go
│   ├── proc.go
│   ├── prompt.go
│   ├── psutil_freebsd.go
│   ├── psutil_linux.go
│   ├── randomname.go
│   ├── request.go
│   ├── sort.go
│   ├── timeoutlock.go
│   ├── unix.go
│   └── webauthn.go
├── validator/
│   └── validator.go
├── version/
│   ├── cache.go
│   ├── utils.go
│   └── version.go
├── virtiofs/
│   ├── systemd.go
│   ├── utils.go
│   └── virtiofs.go
├── vm/
│   ├── constants.go
│   ├── sort.go
│   ├── utils.go
│   └── vm.go
├── vmdk/
│   └── utils.go
├── vpc/
│   ├── constants.go
│   ├── ip.go
│   ├── subnet.go
│   ├── utils.go
│   └── vpc.go
├── vxlan/
│   └── vxlan.go
├── www/
│   ├── .gitignore
│   ├── README.md
│   ├── app/
│   │   ├── Alert.ts
│   │   ├── App.tsx
│   │   ├── Constants.ts
│   │   ├── Csrf.ts
│   │   ├── EditorThemes.ts
│   │   ├── Event.ts
│   │   ├── EventEmitter.ts
│   │   ├── License.ts
│   │   ├── Loader.ts
│   │   ├── References.d.ts
│   │   ├── Router.ts
│   │   ├── Styles.tsx
│   │   ├── Theme.ts
│   │   ├── actions/
│   │   │   ├── AlertActions.ts
│   │   │   ├── AuditActions.ts
│   │   │   ├── AuthorityActions.ts
│   │   │   ├── BalancerActions.ts
│   │   │   ├── BlockActions.ts
│   │   │   ├── CertificateActions.ts
│   │   │   ├── CompletionActions.ts
│   │   │   ├── DatacenterActions.ts
│   │   │   ├── DeviceActions.ts
│   │   │   ├── DiskActions.ts
│   │   │   ├── DomainActions.ts
│   │   │   ├── FirewallActions.ts
│   │   │   ├── ImageActions.ts
│   │   │   ├── InstanceActions.ts
│   │   │   ├── LogActions.ts
│   │   │   ├── NodeActions.ts
│   │   │   ├── OrganizationActions.ts
│   │   │   ├── PlanActions.ts
│   │   │   ├── PodActions.ts
│   │   │   ├── PolicyActions.ts
│   │   │   ├── PoolActions.ts
│   │   │   ├── RelationsActions.ts
│   │   │   ├── SecretActions.ts
│   │   │   ├── SessionActions.ts
│   │   │   ├── SettingsActions.ts
│   │   │   ├── ShapeActions.ts
│   │   │   ├── StorageActions.ts
│   │   │   ├── SubscriptionActions.ts
│   │   │   ├── UserActions.ts
│   │   │   ├── VpcActions.ts
│   │   │   └── ZoneActions.ts
│   │   ├── completion/
│   │   │   ├── Cache.ts
│   │   │   ├── Engine.ts
│   │   │   └── Types.ts
│   │   ├── components/
│   │   │   ├── AdvisoryDialog.tsx
│   │   │   ├── Alert.tsx
│   │   │   ├── AlertDetailed.tsx
│   │   │   ├── AlertNew.tsx
│   │   │   ├── Alerts.tsx
│   │   │   ├── AlertsFilter.tsx
│   │   │   ├── AlertsPage.tsx
│   │   │   ├── Audit.tsx
│   │   │   ├── Audits.tsx
│   │   │   ├── AuditsPage.tsx
│   │   │   ├── Authorities.tsx
│   │   │   ├── AuthoritiesFilter.tsx
│   │   │   ├── AuthoritiesPage.tsx
│   │   │   ├── Authority.tsx
│   │   │   ├── AuthorityDetailed.tsx
│   │   │   ├── AuthorityNew.tsx
│   │   │   ├── Balancer.tsx
│   │   │   ├── BalancerBackend.tsx
│   │   │   ├── BalancerDetailed.tsx
│   │   │   ├── BalancerDomain.tsx
│   │   │   ├── BalancerNew.tsx
│   │   │   ├── Balancers.tsx
│   │   │   ├── BalancersFilter.tsx
│   │   │   ├── BalancersPage.tsx
│   │   │   ├── Block.tsx
│   │   │   ├── BlockDetailed.tsx
│   │   │   ├── BlockNew.tsx
│   │   │   ├── Blocks.tsx
│   │   │   ├── BlocksFilter.tsx
│   │   │   ├── BlocksPage.tsx
│   │   │   ├── Certificate.tsx
│   │   │   ├── CertificateDetailed.tsx
│   │   │   ├── CertificateDomain.tsx
│   │   │   ├── CertificateNew.tsx
│   │   │   ├── Certificates.tsx
│   │   │   ├── CertificatesFilter.tsx
│   │   │   ├── CertificatesPage.tsx
│   │   │   ├── ConfirmButton.tsx
│   │   │   ├── CopyButton.tsx
│   │   │   ├── Datacenter.tsx
│   │   │   ├── DatacenterDetailed.tsx
│   │   │   ├── DatacenterNew.tsx
│   │   │   ├── Datacenters.tsx
│   │   │   ├── DatacentersFilter.tsx
│   │   │   ├── DatacentersPage.tsx
│   │   │   ├── Device.tsx
│   │   │   ├── Devices.tsx
│   │   │   ├── Disk.tsx
│   │   │   ├── DiskDetailed.tsx
│   │   │   ├── DiskNew.tsx
│   │   │   ├── Disks.tsx
│   │   │   ├── DisksFilter.tsx
│   │   │   ├── DisksPage.tsx
│   │   │   ├── Domain.tsx
│   │   │   ├── DomainDetailed.tsx
│   │   │   ├── DomainNew.tsx
│   │   │   ├── DomainRecord.tsx
│   │   │   ├── Domains.tsx
│   │   │   ├── DomainsFilter.tsx
│   │   │   ├── DomainsPage.tsx
│   │   │   ├── Editor.tsx
│   │   │   ├── Firewall.tsx
│   │   │   ├── FirewallDetailed.tsx
│   │   │   ├── FirewallNew.tsx
│   │   │   ├── FirewallRule.tsx
│   │   │   ├── Firewalls.tsx
│   │   │   ├── FirewallsFilter.tsx
│   │   │   ├── FirewallsPage.tsx
│   │   │   ├── Help.tsx
│   │   │   ├── Image.tsx
│   │   │   ├── ImageDetailed.tsx
│   │   │   ├── Images.tsx
│   │   │   ├── ImagesFilter.tsx
│   │   │   ├── ImagesPage.tsx
│   │   │   ├── Instance.tsx
│   │   │   ├── InstanceDetailed.tsx
│   │   │   ├── InstanceImages.tsx
│   │   │   ├── InstanceIscsiDevice.tsx
│   │   │   ├── InstanceLicense.tsx
│   │   │   ├── InstanceMount.tsx
│   │   │   ├── InstanceNew.tsx
│   │   │   ├── InstanceNodePort.tsx
│   │   │   ├── Instances.tsx
│   │   │   ├── InstancesFilter.tsx
│   │   │   ├── InstancesPage.tsx
│   │   │   ├── LoadingBar.tsx
│   │   │   ├── LoadingCircle.tsx
│   │   │   ├── Log.tsx
│   │   │   ├── LogViewer.tsx
│   │   │   ├── Logs.tsx
│   │   │   ├── LogsFilter.tsx
│   │   │   ├── LogsPage.tsx
│   │   │   ├── Main.tsx
│   │   │   ├── MarkdownMemo.tsx
│   │   │   ├── Node.tsx
│   │   │   ├── NodeBlock.tsx
│   │   │   ├── NodeDeploy.tsx
│   │   │   ├── NodeDetailed.tsx
│   │   │   ├── NodeShare.tsx
│   │   │   ├── Nodes.tsx
│   │   │   ├── NodesFilter.tsx
│   │   │   ├── NodesPage.tsx
│   │   │   ├── NonState.tsx
│   │   │   ├── Organization.tsx
│   │   │   ├── OrganizationDetailed.tsx
│   │   │   ├── OrganizationNew.tsx
│   │   │   ├── OrganizationSelect.tsx
│   │   │   ├── Organizations.tsx
│   │   │   ├── OrganizationsFilter.tsx
│   │   │   ├── OrganizationsPage.tsx
│   │   │   ├── Page.tsx
│   │   │   ├── PageButton.tsx
│   │   │   ├── PageCreate.tsx
│   │   │   ├── PageCustom.tsx
│   │   │   ├── PageDateTime.tsx
│   │   │   ├── PageHeader.tsx
│   │   │   ├── PageInfo.tsx
│   │   │   ├── PageInput.tsx
│   │   │   ├── PageInputButton.tsx
│   │   │   ├── PageInputSwitch.tsx
│   │   │   ├── PageNew.tsx
│   │   │   ├── PageNumInput.tsx
│   │   │   ├── PagePanel.tsx
│   │   │   ├── PageSave.tsx
│   │   │   ├── PageSelect.tsx
│   │   │   ├── PageSelectButton.tsx
│   │   │   ├── PageSelectButtonConfirm.tsx
│   │   │   ├── PageSelector.tsx
│   │   │   ├── PageSplit.tsx
│   │   │   ├── PageSwitch.tsx
│   │   │   ├── PageTextArea.tsx
│   │   │   ├── Plan.tsx
│   │   │   ├── PlanDetailed.tsx
│   │   │   ├── PlanEditor.tsx
│   │   │   ├── PlanNew.tsx
│   │   │   ├── PlanStatement.tsx
│   │   │   ├── Plans.tsx
│   │   │   ├── PlansFilter.tsx
│   │   │   ├── PlansPage.tsx
│   │   │   ├── Pod.tsx
│   │   │   ├── PodDeploy.tsx
│   │   │   ├── PodDeployment.tsx
│   │   │   ├── PodDeploymentEdit.tsx
│   │   │   ├── PodDetailed.tsx
│   │   │   ├── PodEditor.tsx
│   │   │   ├── PodMigrate.tsx
│   │   │   ├── PodNew.tsx
│   │   │   ├── PodUnit.tsx
│   │   │   ├── PodWorkspace.tsx
│   │   │   ├── Pods.tsx
│   │   │   ├── PodsFilter.tsx
│   │   │   ├── PodsPage.tsx
│   │   │   ├── Policies.tsx
│   │   │   ├── PoliciesFilter.tsx
│   │   │   ├── PoliciesPage.tsx
│   │   │   ├── Policy.tsx
│   │   │   ├── PolicyDetailed.tsx
│   │   │   ├── PolicyNew.tsx
│   │   │   ├── PolicyRule.tsx
│   │   │   ├── Pool.tsx
│   │   │   ├── PoolDetailed.tsx
│   │   │   ├── PoolNew.tsx
│   │   │   ├── Pools.tsx
│   │   │   ├── PoolsFilter.tsx
│   │   │   ├── PoolsPage.tsx
│   │   │   ├── Relations.tsx
│   │   │   ├── RouterLink.tsx
│   │   │   ├── RouterRedirect.tsx
│   │   │   ├── RouterRoute.tsx
│   │   │   ├── RouterRoutes.tsx
│   │   │   ├── SearchInput.tsx
│   │   │   ├── Secret.tsx
│   │   │   ├── SecretDetailed.tsx
│   │   │   ├── SecretNew.tsx
│   │   │   ├── Secrets.tsx
│   │   │   ├── SecretsFilter.tsx
│   │   │   ├── SecretsPage.tsx
│   │   │   ├── Session.tsx
│   │   │   ├── Sessions.tsx
│   │   │   ├── Settings.tsx
│   │   │   ├── SettingsProvider.tsx
│   │   │   ├── SettingsSecondaryProvider.tsx
│   │   │   ├── Shape.tsx
│   │   │   ├── ShapeDetailed.tsx
│   │   │   ├── ShapeNew.tsx
│   │   │   ├── Shapes.tsx
│   │   │   ├── ShapesFilter.tsx
│   │   │   ├── ShapesPage.tsx
│   │   │   ├── Storage.tsx
│   │   │   ├── StorageDetailed.tsx
│   │   │   ├── StorageNew.tsx
│   │   │   ├── Storages.tsx
│   │   │   ├── StoragesFilter.tsx
│   │   │   ├── StoragesPage.tsx
│   │   │   ├── Subscription.tsx
│   │   │   ├── Switch.tsx
│   │   │   ├── SwitchNull.tsx
│   │   │   ├── User.tsx
│   │   │   ├── UserDetailed.tsx
│   │   │   ├── Users.tsx
│   │   │   ├── UsersFilter.tsx
│   │   │   ├── UsersPage.tsx
│   │   │   ├── Vpc.tsx
│   │   │   ├── VpcArp.tsx
│   │   │   ├── VpcDetailed.tsx
│   │   │   ├── VpcLinkUri.tsx
│   │   │   ├── VpcMap.tsx
│   │   │   ├── VpcNew.tsx
│   │   │   ├── VpcRoute.tsx
│   │   │   ├── VpcSubnet.tsx
│   │   │   ├── Vpcs.tsx
│   │   │   ├── VpcsFilter.tsx
│   │   │   ├── VpcsPage.tsx
│   │   │   ├── Zone.tsx
│   │   │   ├── ZoneDetailed.tsx
│   │   │   ├── ZoneNew.tsx
│   │   │   ├── Zones.tsx
│   │   │   ├── ZonesFilter.tsx
│   │   │   └── ZonesPage.tsx
│   │   ├── dispatcher/
│   │   │   ├── Base.ts
│   │   │   ├── Dispatcher.ts
│   │   │   ├── EventDispatcher.ts
│   │   │   └── LoadingDispatcher.ts
│   │   ├── stores/
│   │   │   ├── AlertsStore.ts
│   │   │   ├── AuditsStore.ts
│   │   │   ├── AuthoritiesStore.ts
│   │   │   ├── BalancersStore.ts
│   │   │   ├── BlocksStore.ts
│   │   │   ├── CertificatesStore.ts
│   │   │   ├── CompletionStore.ts
│   │   │   ├── DatacentersStore.ts
│   │   │   ├── DevicesStore.ts
│   │   │   ├── DisksStore.ts
│   │   │   ├── DomainsNameStore.ts
│   │   │   ├── DomainsStore.ts
│   │   │   ├── FirewallsStore.ts
│   │   │   ├── ImagesDatacenterStore.ts
│   │   │   ├── ImagesStore.ts
│   │   │   ├── InstancesNodeStore.ts
│   │   │   ├── InstancesStore.ts
│   │   │   ├── LoadingStore.ts
│   │   │   ├── LogsStore.ts
│   │   │   ├── NodesStore.ts
│   │   │   ├── NodesZoneStore.ts
│   │   │   ├── OrganizationsStore.ts
│   │   │   ├── PlansStore.ts
│   │   │   ├── PodsStore.ts
│   │   │   ├── PodsUnitStore.ts
│   │   │   ├── PoliciesStore.ts
│   │   │   ├── PoolsStore.ts
│   │   │   ├── SecretsStore.ts
│   │   │   ├── SessionsStore.ts
│   │   │   ├── SettingsStore.ts
│   │   │   ├── ShapesStore.ts
│   │   │   ├── StoragesStore.ts
│   │   │   ├── SubscriptionStore.ts
│   │   │   ├── UserStore.ts
│   │   │   ├── UsersStore.ts
│   │   │   ├── VpcsNameStore.ts
│   │   │   ├── VpcsStore.ts
│   │   │   └── ZonesStore.ts
│   │   ├── types/
│   │   │   ├── AgentTypes.ts
│   │   │   ├── AlertTypes.ts
│   │   │   ├── AuditTypes.ts
│   │   │   ├── AuthorityTypes.ts
│   │   │   ├── BalancerTypes.ts
│   │   │   ├── BlockTypes.ts
│   │   │   ├── CertificateTypes.ts
│   │   │   ├── CompletionTypes.ts
│   │   │   ├── DatacenterTypes.ts
│   │   │   ├── DeviceTypes.ts
│   │   │   ├── DiskTypes.ts
│   │   │   ├── DomainTypes.ts
│   │   │   ├── FirewallTypes.ts
│   │   │   ├── GlobalTypes.ts
│   │   │   ├── ImageTypes.ts
│   │   │   ├── InstanceTypes.ts
│   │   │   ├── LoadingTypes.ts
│   │   │   ├── LogTypes.ts
│   │   │   ├── NodeTypes.ts
│   │   │   ├── OrganizationTypes.ts
│   │   │   ├── PlanTypes.ts
│   │   │   ├── PodTypes.ts
│   │   │   ├── PolicyTypes.ts
│   │   │   ├── PoolTypes.ts
│   │   │   ├── RelationTypes.ts
│   │   │   ├── RouterTypes.ts
│   │   │   ├── SecretTypes.ts
│   │   │   ├── SessionTypes.ts
│   │   │   ├── SettingsTypes.ts
│   │   │   ├── ShapeTypes.ts
│   │   │   ├── StorageTypes.ts
│   │   │   ├── SubscriptionTypes.ts
│   │   │   ├── UserTypes.ts
│   │   │   ├── VpcTypes.ts
│   │   │   └── ZoneTypes.ts
│   │   └── utils/
│   │       ├── AgentUtils.ts
│   │       └── MiscUtils.tsx
│   ├── build.sh
│   ├── build_remote.sh
│   ├── dist/
│   │   ├── index.html
│   │   ├── login.html
│   │   ├── static/
│   │   │   ├── blueprint-datetime2.css
│   │   │   ├── blueprint-icons.css
│   │   │   ├── blueprint3.css
│   │   │   ├── blueprint5.css
│   │   │   ├── global.css
│   │   │   └── normalize.css
│   │   └── uindex.html
│   ├── dist-dev/
│   │   ├── index.html
│   │   ├── login.html
│   │   ├── static/
│   │   │   ├── blueprint-datetime2.css
│   │   │   ├── blueprint-icons.css
│   │   │   ├── blueprint3.css
│   │   │   ├── blueprint5.css
│   │   │   ├── global.css
│   │   │   └── normalize.css
│   │   └── uindex.html
│   ├── index.html
│   ├── index_dist.html
│   ├── login.html
│   ├── package.json
│   ├── styles/
│   │   ├── blueprint.css
│   │   └── global.css
│   ├── tsconfig.json
│   ├── uindex.html
│   ├── uindex_dist.html
│   ├── webpack.config.js
│   └── webpack.dev.config.js
└── zone/
    ├── constants.go
    ├── utils.go
    └── zone.go
Download .txt
Showing preview only (519K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (6772 symbols across 982 files)

FILE: acme/acme.go
  function Generate (line 26) | func Generate(db *database.Database, cert *certificate.Certificate) (
  function create (line 376) | func create(db *database.Database, cert *certificate.Certificate,
  function Renew (line 441) | func Renew(db *database.Database, cert *certificate.Certificate, force b...
  function RenewBackground (line 461) | func RenewBackground(cert *certificate.Certificate, force bool) {

FILE: acme/challenge.go
  type Challenge (line 11) | type Challenge struct
    method Insert (line 17) | func (c *Challenge) Insert(db *database.Database) (err error) {
    method Remove (line 29) | func (c *Challenge) Remove(db *database.Database) (err error) {
  type ChallengeMsg (line 48) | type ChallengeMsg struct
    method Publish (line 53) | func (c *ChallengeMsg) Publish(db *database.Database) (err error) {

FILE: acme/constants.go
  constant AcmeDirectory (line 4) | AcmeDirectory = "https://acme-v02.api.letsencrypt.org/directory"
  constant AcmePath (line 5) | AcmePath      = "/.well-known/acme-challenge/"

FILE: acme/utils.go
  function revoke (line 23) | func revoke(client *acme.Client, authzUrls []string) {
  function ParsePath (line 43) | func ParsePath(path string) string {
  function DnsTxtWait (line 51) | func DnsTxtWait(domain, val string) (found bool, err error) {
  function GetChallenge (line 79) | func GetChallenge(token string) (challenge *Challenge, err error) {
  function newRsaCsr (line 94) | func newRsaCsr(domains []string) (csr []byte, keyPem []byte, err error) {
  function newEcCsr (line 133) | func newEcCsr(domains []string) (csr []byte, keyPem []byte, err error) {

FILE: advisory/advisory.go
  type Advisory (line 18) | type Advisory struct
    method Validate (line 35) | func (a *Advisory) Validate(db *database.Database) (
    method IsFresh (line 151) | func (a *Advisory) IsFresh() bool {
    method Commit (line 172) | func (a *Advisory) Commit(db *database.Database) (err error) {

FILE: advisory/constants.go
  constant None (line 10) | None      = "none"
  constant Low (line 11) | Low       = "low"
  constant Medium (line 12) | Medium    = "medium"
  constant High (line 13) | High      = "high"
  constant Critical (line 14) | Critical  = "critical"
  constant Network (line 15) | Network   = "network"
  constant Adjacent (line 16) | Adjacent  = "adjacent"
  constant Local (line 17) | Local     = "local"
  constant Physical (line 18) | Physical  = "physical"
  constant Required (line 19) | Required  = "required"
  constant Unchanged (line 20) | Unchanged = "unchanged"
  constant Changed (line 21) | Changed   = "changed"
  constant Analyzed (line 23) | Analyzed         = "analyzed"
  constant AwaitingAnalysis (line 24) | AwaitingAnalysis = "awaiting_analysis"
  constant Rejected (line 25) | Rejected         = "rejected"
  constant Undergoing (line 26) | Undergoing       = "undergoing_analysis"
  constant Modified (line 27) | Modified         = "modified"
  constant Deferred (line 28) | Deferred         = "deferred"
  constant Pending (line 29) | Pending          = "pending"
  constant nvdApi (line 31) | nvdApi = "https://services.nvd.nist.gov/rest/json/cves/2.0"

FILE: advisory/utils.go
  type nvdCvssData (line 20) | type nvdCvssData struct
  type nvdCvssMetric (line 34) | type nvdCvssMetric struct
  type nvdMetrics (line 39) | type nvdMetrics struct
  type nvdDescription (line 43) | type nvdDescription struct
  type nvdCve (line 48) | type nvdCve struct
  type nvdVulnerability (line 55) | type nvdVulnerability struct
  type nvdResponse (line 59) | type nvdResponse struct
  function normalizeStatus (line 64) | func normalizeStatus(status string) string {
  function normalizeValue (line 83) | func normalizeValue(val string) string {
  function getOne (line 114) | func getOne(db *database.Database, query *bson.M) (adv *Advisory, err er...
  function getOneNvd (line 127) | func getOneNvd(db *database.Database, cveId string) (
  function GetOneLimit (line 238) | func GetOneLimit(db *database.Database, cveId string) (
  function GetOne (line 276) | func GetOne(db *database.Database, cveId string) (adv *Advisory, err err...
  function Remove (line 300) | func Remove(db *database.Database, advId bson.ObjectID) (err error) {

FILE: agent/agent.go
  constant help (line 23) | help = `
  function main (line 36) | func main() {
  function daemonFork (line 411) | func daemonFork() (err error) {

FILE: agent/constants/constants.go
  constant Version (line 4) | Version      = "1.0.3248.95"
  constant ImdsConfPath (line 5) | ImdsConfPath = "/etc/pritunl-imds.json"
  constant ImdsLogPath (line 6) | ImdsLogPath  = "/var/log/pritunl-imds.log"

FILE: agent/imds/imds.go
  type Imds (line 37) | type Imds struct
    method NewRequest (line 50) | func (m *Imds) NewRequest(method, pth string, data interface{}) (
    method Get (line 89) | func (m *Imds) Get(query string) (val string, err error) {
    method SyncReady (line 147) | func (m *Imds) SyncReady(timeout time.Duration) (err error) {
    method Sync (line 180) | func (m *Imds) Sync() (ready bool, err error) {
    method SetInitialized (line 330) | func (m *Imds) SetInitialized() {
    method RunSync (line 337) | func (m *Imds) RunSync(fast bool) {
    method SyncStatus (line 391) | func (m *Imds) SyncStatus(status string) (err error) {
    method Wait (line 405) | func (m *Imds) Wait() (err error) {
    method Init (line 411) | func (m *Imds) Init(eng *engine.Engine) (err error) {
    method OpenLog (line 430) | func (m *Imds) OpenLog() (err error) {
    method Close (line 441) | func (m *Imds) Close() {
  type SyncResp (line 141) | type SyncResp struct

FILE: agent/imds/journal.go
  type Journal (line 8) | type Journal struct
    method Open (line 17) | func (j *Journal) Open() (err error) {
    method Close (line 34) | func (j *Journal) Close() {

FILE: agent/imds/sync.go
  type StateData (line 18) | type StateData struct
  method GetState (line 22) | func (m *Imds) GetState(curHash uint32) (data *StateData, err error) {
  function SetStatus (line 63) | func SetStatus(status string) {

FILE: agent/imds/utils.go
  function GetState (line 12) | func GetState() string {
  function SetState (line 28) | func SetState(state string) (err error) {

FILE: agent/logging/file.go
  type File (line 17) | type File struct
    method GetOutput (line 25) | func (f *File) GetOutput() (entries []*types.Entry) {
    method followJournal (line 36) | func (f *File) followJournal() (err error) {
    method Open (line 111) | func (f *File) Open() (err error) {
    method Close (line 163) | func (f *File) Close() (err error) {
  function NewFile (line 189) | func NewFile(path string) *File {

FILE: agent/logging/handler.go
  type Handler (line 7) | type Handler interface

FILE: agent/logging/logging.go
  constant maxCapacity (line 16) | maxCapacity = 128 * 1024
  type Redirect (line 18) | type Redirect struct
    method GetOutput (line 30) | func (r *Redirect) GetOutput() (entries []*types.Entry) {
    method handleOutput (line 41) | func (r *Redirect) handleOutput(reader *os.File, level int32) {
    method Open (line 67) | func (r *Redirect) Open() (err error) {
    method Close (line 110) | func (r *Redirect) Close() (err error) {

FILE: agent/logging/systemd.go
  type Systemd (line 20) | type Systemd struct
    method GetOutput (line 34) | func (s *Systemd) GetOutput() (entries []*types.Entry) {
    method followJournal (line 45) | func (s *Systemd) followJournal() (err error) {
    method Open (line 173) | func (s *Systemd) Open() (err error) {
    method Close (line 225) | func (s *Systemd) Close() (err error) {
  type journalEntry (line 28) | type journalEntry struct
  function NewSystemd (line 251) | func NewSystemd(unit string) *Systemd {

FILE: agent/utils/sanitize.go
  type fileOp (line 10) | type fileOp struct
  type findOp (line 16) | type findOp struct
  function Sanitize (line 22) | func Sanitize() (err error) {
  function SanitizeImds (line 116) | func SanitizeImds() (err error) {

FILE: agent/utils/sys.go
  function Read (line 12) | func Read(path string) (data string, err error) {
  function DelayExit (line 25) | func DelayExit(code int, delay time.Duration) {

FILE: aggregate/block.go
  type BlockPipe (line 13) | type BlockPipe struct
  type BlocksPipe (line 18) | type BlocksPipe struct
  type BlockAggregate (line 23) | type BlockAggregate struct
  function GetBlockPaged (line 29) | func GetBlockPaged(db *database.Database, query *bson.M, page,

FILE: aggregate/deployment.go
  type DeploymentPipe (line 19) | type DeploymentPipe struct
  type Deployment (line 28) | type Deployment struct
  function GetDeployments (line 69) | func GetDeployments(db *database.Database, unt *unit.Unit) (

FILE: aggregate/disk.go
  type DiskPipe (line 14) | type DiskPipe struct
  type DisksPipe (line 19) | type DisksPipe struct
  type DiskBackup (line 24) | type DiskBackup struct
  type DiskAggregate (line 29) | type DiskAggregate struct
  function GetDiskPaged (line 34) | func GetDiskPaged(db *database.Database, query *bson.M, page,

FILE: aggregate/domain.go
  type Domain (line 13) | type Domain struct
  type DomainsPipe (line 18) | type DomainsPipe struct
  function GetDomainPaged (line 23) | func GetDomainPaged(db *database.Database, query *bson.M, page,

FILE: aggregate/instance.go
  type InstancePipe (line 27) | type InstancePipe struct
  type InstancesPipe (line 34) | type InstancesPipe struct
  type InstanceInfo (line 39) | type InstanceInfo struct
  type InstanceAggregate (line 54) | type InstanceAggregate struct
  function GetInstancePaged (line 59) | func GetInstancePaged(db *database.Database, query *bson.M, page,

FILE: aggregate/pod.go
  function sortUnits (line 15) | func sortUnits(units []*unit.Unit) {
  type PodPipe (line 21) | type PodPipe struct
  type Metadata (line 26) | type Metadata struct
  type PodsPipe (line 30) | type PodsPipe struct
  type PodAggregate (line 35) | type PodAggregate struct
  function GetPod (line 40) | func GetPod(db *database.Database, usrId bson.ObjectID, query *bson.M) (
  function GetPodsPaged (line 96) | func GetPodsPaged(db *database.Database, usrId bson.ObjectID,

FILE: aggregate/shape.go
  type ShapePipe (line 14) | type ShapePipe struct
  type ShapesPipe (line 19) | type ShapesPipe struct
  function GetShapePaged (line 24) | func GetShapePaged(db *database.Database, query *bson.M, page,

FILE: ahandlers/alert.go
  type alertData (line 21) | type alertData struct
  type alertsData (line 35) | type alertsData struct
  function alertPut (line 40) | func alertPut(c *gin.Context) {
  function alertPost (line 115) | func alertPost(c *gin.Context) {
  function alertDelete (line 171) | func alertDelete(c *gin.Context) {
  function alertsDelete (line 195) | func alertsDelete(c *gin.Context) {
  function alertGet (line 220) | func alertGet(c *gin.Context) {
  function alertsGet (line 244) | func alertsGet(c *gin.Context) {

FILE: ahandlers/audit.go
  type auditsData (line 13) | type auditsData struct
  function auditsGet (line 18) | func auditsGet(c *gin.Context) {

FILE: ahandlers/auth.go
  function authStateGet (line 25) | func authStateGet(c *gin.Context) {
  type authData (line 40) | type authData struct
  function authSessionPost (line 45) | func authSessionPost(c *gin.Context) {
  type secondaryData (line 193) | type secondaryData struct
  function authSecondaryPost (line 199) | func authSecondaryPost(c *gin.Context) {
  function logoutGet (line 362) | func logoutGet(c *gin.Context) {
  function authRequestGet (line 392) | func authRequestGet(c *gin.Context) {
  function authCallbackGet (line 396) | func authCallbackGet(c *gin.Context) {
  function authWanRegisterGet (line 564) | func authWanRegisterGet(c *gin.Context) {
  type authWanRegisterData (line 644) | type authWanRegisterData struct
  function authWanRegisterPost (line 649) | func authWanRegisterPost(c *gin.Context) {
  function authWanRequestGet (line 789) | func authWanRequestGet(c *gin.Context) {
  type authWanRespondData (line 844) | type authWanRespondData struct
  function authWanRespondPost (line 848) | func authWanRespondPost(c *gin.Context) {

FILE: ahandlers/authority.go
  type authorityData (line 21) | type authorityData struct
  type authoritiesData (line 33) | type authoritiesData struct
  function authorityPut (line 38) | func authorityPut(c *gin.Context) {
  function authorityPost (line 109) | func authorityPost(c *gin.Context) {
  function authorityDelete (line 161) | func authorityDelete(c *gin.Context) {
  function authoritiesDelete (line 185) | func authoritiesDelete(c *gin.Context) {
  function authorityGet (line 213) | func authorityGet(c *gin.Context) {
  function authoritiesGet (line 237) | func authoritiesGet(c *gin.Context) {

FILE: ahandlers/balancer.go
  type balancerData (line 21) | type balancerData struct
  type balancersData (line 36) | type balancersData struct
  function balancerPut (line 41) | func balancerPut(c *gin.Context) {
  function balancerPost (line 120) | func balancerPost(c *gin.Context) {
  function balancerDelete (line 177) | func balancerDelete(c *gin.Context) {
  function balancersDelete (line 201) | func balancersDelete(c *gin.Context) {
  function balancerGet (line 229) | func balancerGet(c *gin.Context) {
  function balancersGet (line 255) | func balancersGet(c *gin.Context) {

FILE: ahandlers/block.go
  type blockData (line 23) | type blockData struct
  type blocksData (line 37) | type blocksData struct
  function blockPut (line 42) | func blockPut(c *gin.Context) {
  function blockPost (line 115) | func blockPost(c *gin.Context) {
  function blockDelete (line 169) | func blockDelete(c *gin.Context) {
  function blocksDelete (line 204) | func blocksDelete(c *gin.Context) {
  function blockGet (line 243) | func blockGet(c *gin.Context) {
  function blocksGet (line 267) | func blocksGet(c *gin.Context) {

FILE: ahandlers/certificate.go
  type certificateData (line 23) | type certificateData struct
  type certificatesData (line 38) | type certificatesData struct
  function certificatePut (line 43) | func certificatePut(c *gin.Context) {
  function certificatePost (line 126) | func certificatePost(c *gin.Context) {
  function certificateDelete (line 187) | func certificateDelete(c *gin.Context) {
  function certificatesDelete (line 222) | func certificatesDelete(c *gin.Context) {
  function certificateGet (line 261) | func certificateGet(c *gin.Context) {
  function certificatesGet (line 290) | func certificatesGet(c *gin.Context) {

FILE: ahandlers/check.go
  function checkGet (line 7) | func checkGet(c *gin.Context) {

FILE: ahandlers/completion.go
  function completionGet (line 28) | func completionGet(c *gin.Context) {

FILE: ahandlers/csrf.go
  type csrfData (line 12) | type csrfData struct
  function csrfGet (line 19) | func csrfGet(c *gin.Context) {

FILE: ahandlers/datacenter.go
  type datacenterData (line 22) | type datacenterData struct
  type datacentersData (line 37) | type datacentersData struct
  function datacenterPut (line 42) | func datacenterPut(c *gin.Context) {
  function datacenterPost (line 119) | func datacenterPost(c *gin.Context) {
  function datacenterDelete (line 174) | func datacenterDelete(c *gin.Context) {
  function datacentersDelete (line 209) | func datacentersDelete(c *gin.Context) {
  function datacenterGet (line 248) | func datacenterGet(c *gin.Context) {
  function datacentersGet (line 272) | func datacentersGet(c *gin.Context) {

FILE: ahandlers/devices.go
  type deviceData (line 21) | type deviceData struct
  function devicePut (line 29) | func devicePut(c *gin.Context) {
  function devicePost (line 86) | func devicePost(c *gin.Context) {
  function deviceDelete (line 130) | func deviceDelete(c *gin.Context) {
  function devicesGet (line 154) | func devicesGet(c *gin.Context) {
  function deviceAlertPost (line 172) | func deviceAlertPost(c *gin.Context) {
  function deviceMethodPost (line 217) | func deviceMethodPost(c *gin.Context) {
  type devicesWanRegisterRespData (line 230) | type devicesWanRegisterRespData struct
  function deviceWanRegisterGet (line 235) | func deviceWanRegisterGet(c *gin.Context) {
  type devicesWanRegisterData (line 284) | type devicesWanRegisterData struct
  function deviceWanRegisterPost (line 289) | func deviceWanRegisterPost(c *gin.Context) {

FILE: ahandlers/disk.go
  type diskData (line 27) | type diskData struct
  type disksMultiData (line 49) | type disksMultiData struct
  type disksData (line 54) | type disksData struct
  function diskPut (line 59) | func diskPut(c *gin.Context) {
  function diskPost (line 174) | func diskPost(c *gin.Context) {
  function disksPut (line 285) | func disksPut(c *gin.Context) {
  function diskDelete (line 327) | func diskDelete(c *gin.Context) {
  function disksDelete (line 386) | func disksDelete(c *gin.Context) {
  function diskGet (line 425) | func diskGet(c *gin.Context) {
  function disksGet (line 449) | func disksGet(c *gin.Context) {

FILE: ahandlers/domain.go
  type domainData (line 20) | type domainData struct
  type domainsData (line 31) | type domainsData struct
  function domainPut (line 36) | func domainPut(c *gin.Context) {
  function domainPost (line 114) | func domainPost(c *gin.Context) {
  function domainDelete (line 161) | func domainDelete(c *gin.Context) {
  function domainsDelete (line 185) | func domainsDelete(c *gin.Context) {
  function domainGet (line 210) | func domainGet(c *gin.Context) {
  function domainsGet (line 241) | func domainsGet(c *gin.Context) {

FILE: ahandlers/event.go
  constant writeTimeout (line 19) | writeTimeout = 10 * time.Second
  constant pingInterval (line 20) | pingInterval = 30 * time.Second
  constant pingWait (line 21) | pingWait     = 40 * time.Second
  function eventGet (line 24) | func eventGet(c *gin.Context) {

FILE: ahandlers/firewall.go
  type firewallData (line 20) | type firewallData struct
  type firewallsData (line 29) | type firewallsData struct
  function firewallPut (line 34) | func firewallPut(c *gin.Context) {
  function firewallPost (line 96) | func firewallPost(c *gin.Context) {
  function firewallDelete (line 142) | func firewallDelete(c *gin.Context) {
  function firewallsDelete (line 177) | func firewallsDelete(c *gin.Context) {
  function firewallGet (line 213) | func firewallGet(c *gin.Context) {
  function firewallsGet (line 237) | func firewallsGet(c *gin.Context) {

FILE: ahandlers/handlers.go
  function Register (line 19) | func Register(engine *gin.Engine) {
  function init (line 284) | func init() {

FILE: ahandlers/image.go
  type imageData (line 21) | type imageData struct
  type imagesData (line 28) | type imagesData struct
  function imagePut (line 33) | func imagePut(c *gin.Context) {
  function imageDelete (line 91) | func imageDelete(c *gin.Context) {
  function imagesDelete (line 116) | func imagesDelete(c *gin.Context) {
  function imageGet (line 142) | func imageGet(c *gin.Context) {
  function imagesGet (line 162) | func imagesGet(c *gin.Context) {

FILE: ahandlers/instance.go
  type instanceData (line 34) | type instanceData struct
  type instanceMultiData (line 79) | type instanceMultiData struct
  type instancesData (line 84) | type instancesData struct
  function instancePut (line 89) | func instancePut(c *gin.Context) {
  function instancePost (line 235) | func instancePost(c *gin.Context) {
  function instancesPut (line 435) | func instancesPut(c *gin.Context) {
  function instanceDelete (line 478) | func instanceDelete(c *gin.Context) {
  function instancesDelete (line 517) | func instancesDelete(c *gin.Context) {
  function instanceGet (line 553) | func instanceGet(c *gin.Context) {
  function instancesGet (line 598) | func instancesGet(c *gin.Context) {
  function instanceVncGet (line 767) | func instanceVncGet(c *gin.Context) {

FILE: ahandlers/license.go
  type licenseData (line 12) | type licenseData struct
  function licensePut (line 16) | func licensePut(c *gin.Context) {

FILE: ahandlers/log.go
  type logsData (line 17) | type logsData struct
  function logGet (line 22) | func logGet(c *gin.Context) {
  function logsGet (line 45) | func logsGet(c *gin.Context) {

FILE: ahandlers/node.go
  type nodeData (line 30) | type nodeData struct
  type nodesData (line 80) | type nodesData struct
  type nodeInitData (line 85) | type nodeInitData struct
  function nodePut (line 96) | func nodePut(c *gin.Context) {
  function nodeOperationPut (line 278) | func nodeOperationPut(c *gin.Context) {
  function nodeInitPost (line 327) | func nodeInitPost(c *gin.Context) {
  function nodeDelete (line 584) | func nodeDelete(c *gin.Context) {
  function nodeGet (line 619) | func nodeGet(c *gin.Context) {
  function nodesGet (line 644) | func nodesGet(c *gin.Context) {

FILE: ahandlers/organization.go
  type organizationData (line 22) | type organizationData struct
  type organizationsData (line 29) | type organizationsData struct
  function organizationPut (line 34) | func organizationPut(c *gin.Context) {
  function organizationPost (line 92) | func organizationPost(c *gin.Context) {
  function organizationDelete (line 153) | func organizationDelete(c *gin.Context) {
  function organizationGet (line 188) | func organizationGet(c *gin.Context) {
  function organizationsGet (line 212) | func organizationsGet(c *gin.Context) {

FILE: ahandlers/plan.go
  type planData (line 19) | type planData struct
  type plansData (line 27) | type plansData struct
  function planPut (line 32) | func planPut(c *gin.Context) {
  function planPost (line 97) | func planPost(c *gin.Context) {
  function planDelete (line 147) | func planDelete(c *gin.Context) {
  function plansDelete (line 171) | func plansDelete(c *gin.Context) {
  function planGet (line 196) | func planGet(c *gin.Context) {
  function plansGet (line 220) | func plansGet(c *gin.Context) {

FILE: ahandlers/pod.go
  type podData (line 29) | type podData struct
  type podsData (line 40) | type podsData struct
  type podsDeployData (line 45) | type podsDeployData struct
  type deploymentData (line 50) | type deploymentData struct
  type specsData (line 55) | type specsData struct
  function podPut (line 60) | func podPut(c *gin.Context) {
  function podDraftsPut (line 142) | func podDraftsPut(c *gin.Context) {
  function podDeployPut (line 181) | func podDeployPut(c *gin.Context) {
  function podPost (line 245) | func podPost(c *gin.Context) {
  function podDelete (line 305) | func podDelete(c *gin.Context) {
  function podsDelete (line 341) | func podsDelete(c *gin.Context) {
  function podGet (line 381) | func podGet(c *gin.Context) {
  function podsGet (line 418) | func podsGet(c *gin.Context) {
  type PodUnit (line 519) | type PodUnit struct
  function podUnitGet (line 526) | func podUnitGet(c *gin.Context) {
  function podUnitDeploymentsPut (line 598) | func podUnitDeploymentsPut(c *gin.Context) {
  function podUnitDeploymentPost (line 678) | func podUnitDeploymentPost(c *gin.Context) {
  function podUnitDeploymentPut (line 725) | func podUnitDeploymentPut(c *gin.Context) {
  function podUnitDeploymentLogGet (line 788) | func podUnitDeploymentLogGet(c *gin.Context) {
  function podUnitSpecsGet (line 848) | func podUnitSpecsGet(c *gin.Context) {
  function podUnitSpecGet (line 903) | func podUnitSpecGet(c *gin.Context) {

FILE: ahandlers/policy.go
  type policyData (line 22) | type policyData struct
  type policiesData (line 38) | type policiesData struct
  function policyPut (line 43) | func policyPut(c *gin.Context) {
  function policyPost (line 113) | func policyPost(c *gin.Context) {
  function policyDelete (line 163) | func policyDelete(c *gin.Context) {
  function policiesDelete (line 198) | func policiesDelete(c *gin.Context) {
  function policyGet (line 237) | func policyGet(c *gin.Context) {
  function policiesGet (line 261) | func policiesGet(c *gin.Context) {

FILE: ahandlers/pool.go
  type poolData (line 22) | type poolData struct
  type poolsData (line 32) | type poolsData struct
  function poolPut (line 37) | func poolPut(c *gin.Context) {
  function poolPost (line 97) | func poolPost(c *gin.Context) {
  function poolDelete (line 150) | func poolDelete(c *gin.Context) {
  function poolsDelete (line 174) | func poolsDelete(c *gin.Context) {
  function poolGet (line 199) | func poolGet(c *gin.Context) {
  function poolsGet (line 223) | func poolsGet(c *gin.Context) {

FILE: ahandlers/relations.go
  type relationsData (line 11) | type relationsData struct
  function relationsGet (line 17) | func relationsGet(c *gin.Context) {

FILE: ahandlers/secret.go
  type secretData (line 22) | type secretData struct
  type secretsData (line 34) | type secretsData struct
  function secretPut (line 39) | func secretPut(c *gin.Context) {
  function secretPost (line 112) | func secretPost(c *gin.Context) {
  function secretDelete (line 164) | func secretDelete(c *gin.Context) {
  function secretsDelete (line 199) | func secretsDelete(c *gin.Context) {
  function secretGet (line 238) | func secretGet(c *gin.Context) {
  function secretsGet (line 267) | func secretsGet(c *gin.Context) {

FILE: ahandlers/session.go
  function sessionsGet (line 15) | func sessionsGet(c *gin.Context) {
  function sessionDelete (line 41) | func sessionDelete(c *gin.Context) {

FILE: ahandlers/settings.go
  type settingsData (line 13) | type settingsData struct
  function getSettingsData (line 31) | func getSettingsData() *settingsData {
  function settingsGet (line 50) | func settingsGet(c *gin.Context) {
  function settingsPut (line 55) | func settingsPut(c *gin.Context) {

FILE: ahandlers/shape.go
  type shapeData (line 21) | type shapeData struct
  type shapesData (line 36) | type shapesData struct
  function shapePut (line 41) | func shapePut(c *gin.Context) {
  function shapePost (line 115) | func shapePost(c *gin.Context) {
  function shapeDelete (line 166) | func shapeDelete(c *gin.Context) {
  function shapesDelete (line 201) | func shapesDelete(c *gin.Context) {
  function shapeGet (line 237) | func shapeGet(c *gin.Context) {
  function shapesGet (line 261) | func shapesGet(c *gin.Context) {

FILE: ahandlers/static.go
  function staticPath (line 16) | func staticPath(c *gin.Context, pth string, cache bool) {
  function staticIndexGet (line 43) | func staticIndexGet(c *gin.Context) {
  function staticLoginGet (line 59) | func staticLoginGet(c *gin.Context) {
  function staticLogoGet (line 63) | func staticLogoGet(c *gin.Context) {
  function staticGet (line 67) | func staticGet(c *gin.Context) {
  function staticTestingGet (line 71) | func staticTestingGet(c *gin.Context) {

FILE: ahandlers/storage.go
  type storageData (line 23) | type storageData struct
  type storagesData (line 35) | type storagesData struct
  function storagePut (line 40) | func storagePut(c *gin.Context) {
  function storagePost (line 122) | func storagePost(c *gin.Context) {
  function storageDelete (line 185) | func storageDelete(c *gin.Context) {
  function storagesDelete (line 209) | func storagesDelete(c *gin.Context) {
  function storageGet (line 237) | func storageGet(c *gin.Context) {
  function storagesGet (line 270) | func storagesGet(c *gin.Context) {

FILE: ahandlers/subscription.go
  type subscriptionPostData (line 16) | type subscriptionPostData struct
  function subscriptionGet (line 20) | func subscriptionGet(c *gin.Context) {
  function subscriptionUpdateGet (line 28) | func subscriptionUpdateGet(c *gin.Context) {
  function subscriptionPost (line 47) | func subscriptionPost(c *gin.Context) {

FILE: ahandlers/theme.go
  type themeData (line 12) | type themeData struct
  function themePut (line 17) | func themePut(c *gin.Context) {

FILE: ahandlers/user.go
  type userData (line 20) | type userData struct
  type usersData (line 34) | type usersData struct
  function userGet (line 39) | func userGet(c *gin.Context) {
  function userPut (line 66) | func userPut(c *gin.Context) {
  function userPost (line 184) | func userPost(c *gin.Context) {
  function usersGet (line 247) | func usersGet(c *gin.Context) {
  function usersDelete (line 360) | func usersDelete(c *gin.Context) {

FILE: ahandlers/vpc.go
  type vpcData (line 22) | type vpcData struct
  type vpcsData (line 36) | type vpcsData struct
  function vpcPut (line 41) | func vpcPut(c *gin.Context) {
  function vpcPost (line 122) | func vpcPost(c *gin.Context) {
  function vpcDelete (line 180) | func vpcDelete(c *gin.Context) {
  function vpcsDelete (line 215) | func vpcsDelete(c *gin.Context) {
  function vpcGet (line 251) | func vpcGet(c *gin.Context) {
  function vpcRoutesGet (line 277) | func vpcRoutesGet(c *gin.Context) {
  function vpcRoutesPut (line 301) | func vpcRoutesPut(c *gin.Context) {
  function vpcsGet (line 357) | func vpcsGet(c *gin.Context) {

FILE: ahandlers/zone.go
  type zoneData (line 22) | type zoneData struct
  type zonesData (line 29) | type zonesData struct
  function zonePut (line 34) | func zonePut(c *gin.Context) {
  function zonePost (line 90) | func zonePost(c *gin.Context) {
  function zoneDelete (line 134) | func zoneDelete(c *gin.Context) {
  function zonesDelete (line 169) | func zonesDelete(c *gin.Context) {
  function zoneGet (line 208) | func zoneGet(c *gin.Context) {
  function zonesGet (line 232) | func zonesGet(c *gin.Context) {

FILE: alert/alert.go
  type Alert (line 11) | type Alert struct
    method Validate (line 25) | func (a *Alert) Validate(db *database.Database) (
    method Commit (line 92) | func (a *Alert) Commit(db *database.Database) (err error) {
    method CommitFields (line 103) | func (a *Alert) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 116) | func (a *Alert) Insert(db *database.Database) (err error) {

FILE: alert/constants.go
  constant Low (line 4) | Low    = 1
  constant Medium (line 5) | Medium = 5
  constant High (line 6) | High   = 10
  constant InstanceOffline (line 10) | InstanceOffline = "instance_offline"

FILE: alert/utils.go
  function Get (line 11) | func Get(db *database.Database, alertId bson.ObjectID) (
  function GetOrg (line 25) | func GetOrg(db *database.Database, orgId, alertId bson.ObjectID) (
  function GetMulti (line 43) | func GetMulti(db *database.Database, alertIds []bson.ObjectID) (
  function GetAll (line 83) | func GetAll(db *database.Database) (alerts []*Alert, err error) {
  function GetAllPaged (line 117) | func GetAllPaged(db *database.Database, query *bson.M,
  function GetRoles (line 180) | func GetRoles(db *database.Database, roles []string) (
  function GetRolesMapped (line 224) | func GetRolesMapped(db *database.Database, rolesSet set.Set) (
  function Remove (line 252) | func Remove(db *database.Database,
  function RemoveOrg (line 268) | func RemoveOrg(db *database.Database, orgId, alertId bson.ObjectID) (
  function RemoveMulti (line 290) | func RemoveMulti(db *database.Database, alertIds []bson.ObjectID) (
  function RemoveMultiOrg (line 308) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: alertevent/alertevent.go
  type Alert (line 14) | type Alert struct
    method DocId (line 27) | func (a *Alert) DocId() string {
    method Key (line 39) | func (a *Alert) Key(devc *device.Device) string {
    method Lock (line 52) | func (a *Alert) Lock(db *database.Database, devc *device.Device) (
    method FormattedTextMessage (line 74) | func (a *Alert) FormattedTextMessage() string {
    method FormattedCallMessage (line 78) | func (a *Alert) FormattedCallMessage() string {
    method Send (line 82) | func (a *Alert) Send(db *database.Database, roles []string) (err error) {
  function New (line 166) | func New(roles []string, source bson.ObjectID,

FILE: alertevent/utils.go
  type AlertParams (line 24) | type AlertParams struct
  function SendTest (line 31) | func SendTest(db *database.Database, devc *device.Device) (
  function Send (line 47) | func Send(number, message, alertType string) (

FILE: arp/arp.go
  type Record (line 18) | type Record struct
  type entry (line 23) | type entry struct
  function GetRecords (line 31) | func GetRecords(namespace string) (records set.Set, err error) {
  function BuildState (line 80) | func BuildState(instances []*instance.Instance,
  function ApplyState (line 133) | func ApplyState(namespace string, oldState, newState set.Set) (

FILE: audit/audit.go
  type Fields (line 13) | type Fields
  type Audit (line 15) | type Audit struct
    method Insert (line 24) | func (a *Audit) Insert(db *database.Database) (err error) {

FILE: audit/constants.go
  constant AdminLogin (line 4) | AdminLogin                 = "admin_login"
  constant AdminLoginFailed (line 5) | AdminLoginFailed           = "admin_login_failed"
  constant AdminAuthFailed (line 6) | AdminAuthFailed            = "admin_auth_failed"
  constant AdminLogout (line 7) | AdminLogout                = "admin_logout"
  constant AdminPrimaryApprove (line 8) | AdminPrimaryApprove        = "admin_primary_approve"
  constant AdminSecondaryApprove (line 9) | AdminSecondaryApprove      = "admin_secondary_approve"
  constant AdminDeviceApprove (line 10) | AdminDeviceApprove         = "admin_device_approve"
  constant AdminDeviceRegisterRequest (line 11) | AdminDeviceRegisterRequest = "admin_device_register_request"
  constant AdminDeviceRegister (line 12) | AdminDeviceRegister        = "admin_device_register"
  constant ProxyLogin (line 14) | ProxyLogin                 = "proxy_login"
  constant ProxyLoginFailed (line 15) | ProxyLoginFailed           = "proxy_login_failed"
  constant ProxyAuthFailed (line 16) | ProxyAuthFailed            = "proxy_auth_failed"
  constant ProxyLogout (line 17) | ProxyLogout                = "proxy_logout"
  constant ProxyPrimaryApprove (line 18) | ProxyPrimaryApprove        = "proxy_primary_approve"
  constant ProxySecondaryApprove (line 19) | ProxySecondaryApprove      = "proxy_secondary_approve"
  constant ProxyDeviceApprove (line 20) | ProxyDeviceApprove         = "proxy_device_approve"
  constant ProxyDeviceRegisterRequest (line 21) | ProxyDeviceRegisterRequest = "proxy_device_register_request"
  constant ProxyDeviceRegister (line 22) | ProxyDeviceRegister        = "proxy_device_register"
  constant UserLogin (line 24) | UserLogin                 = "user_login"
  constant UserLoginFailed (line 25) | UserLoginFailed           = "user_login_failed"
  constant UserAuthFailed (line 26) | UserAuthFailed            = "user_auth_failed"
  constant UserLogout (line 27) | UserLogout                = "user_logout"
  constant UserLogoutAll (line 28) | UserLogoutAll             = "user_logout_all"
  constant UserPrimaryApprove (line 29) | UserPrimaryApprove        = "user_primary_approve"
  constant UserSecondaryApprove (line 30) | UserSecondaryApprove      = "user_secondary_approve"
  constant UserDeviceApprove (line 31) | UserDeviceApprove         = "user_device_approve"
  constant UserDeviceRegisterRequest (line 32) | UserDeviceRegisterRequest = "user_device_register_request"
  constant UserDeviceRegister (line 33) | UserDeviceRegister        = "user_device_register"
  constant UserAccountDisable (line 34) | UserAccountDisable        = "user_account_disable"
  constant DeviceRegister (line 36) | DeviceRegister       = "device_register"
  constant DeviceRegisterFailed (line 37) | DeviceRegisterFailed = "device_register_failed"
  constant DuoApprove (line 38) | DuoApprove           = "duo_approve"
  constant DuoDeny (line 39) | DuoDeny              = "duo_deny"
  constant OneLoginApprove (line 40) | OneLoginApprove      = "one_login_approve"
  constant OneLoginDeny (line 41) | OneLoginDeny         = "one_login_deny"
  constant OktaApprove (line 42) | OktaApprove          = "okta_approve"
  constant OktaDeny (line 43) | OktaDeny             = "okta_deny"

FILE: audit/utils.go
  function Get (line 15) | func Get(db *database.Database, adtId string) (
  function GetAll (line 29) | func GetAll(db *database.Database, userId bson.ObjectID,
  function New (line 87) | func New(db *database.Database, r *http.Request,

FILE: auth/auth.go
  type authData (line 17) | type authData struct
  type Token (line 21) | type Token struct
    method Remove (line 30) | func (t *Token) Remove(db *database.Database) (err error) {

FILE: auth/authzero.go
  constant AuthZero (line 20) | AuthZero = "authzero"
  function AuthZeroRequest (line 23) | func AuthZeroRequest(db *database.Database, location, query string,
  type authZeroJwks (line 118) | type authZeroJwks struct
  type authZeroTokenReq (line 122) | type authZeroTokenReq struct
  type authZeroTokenData (line 129) | type authZeroTokenData struct
  type authZeroToken (line 135) | type authZeroToken struct
  type authZeroAppAuthorization (line 144) | type authZeroAppAuthorization struct
  type authZeroAppMetadata (line 149) | type authZeroAppMetadata struct
  type authZeroUser (line 153) | type authZeroUser struct
  function authZeroGetToken (line 302) | func authZeroGetToken(provider *settings.Provider) (token string, err er...
  function AuthZeroRoles (line 362) | func AuthZeroRoles(provider *settings.Provider, username string) (
  function AuthZeroSync (line 451) | func AuthZeroSync(db *database.Database, usr *user.User,

FILE: auth/azure.go
  constant Azure (line 20) | Azure = "azure"
  function azureGetUrls (line 23) | func azureGetUrls(provider *settings.Provider) (loginUrl, graphUrl strin...
  function AzureRequest (line 41) | func AzureRequest(db *database.Database, location, query string,
  type azureTokenData (line 138) | type azureTokenData struct
  type azureMemberData (line 144) | type azureMemberData struct
  type azureUserData (line 149) | type azureUserData struct
  type azureGroupData (line 155) | type azureGroupData struct
  function azureGetToken (line 159) | func azureGetToken(provider *settings.Provider) (token string, err error) {
  function AzureRoles (line 214) | func AzureRoles(provider *settings.Provider, username string) (
  function AzureSync (line 335) | func AzureSync(provider *settings.Provider, username string) (

FILE: auth/constants.go
  constant Admin (line 4) | Admin = "admin"
  constant User (line 5) | User  = "user"

FILE: auth/errortypes.go
  type InvalidState (line 7) | type InvalidState struct

FILE: auth/google.go
  constant Google (line 22) | Google = "google"
  function GoogleRequest (line 25) | func GoogleRequest(db *database.Database, location, query string) (
  function GoogleRoles (line 113) | func GoogleRoles(provider *settings.Provider, username string) (
  function GoogleSync (line 166) | func GoogleSync(db *database.Database, usr *user.User) (

FILE: auth/handler.go
  function Local (line 25) | func Local(db *database.Database, username, password string) (
  function Request (line 65) | func Request(c *gin.Context, typ string) {
  function Callback (line 157) | func Callback(db *database.Database, sig, query string) (

FILE: auth/jumpcloud.go
  constant JumpCloud (line 19) | JumpCloud = "jumpcloud"
  type jumpcloudResponse (line 22) | type jumpcloudResponse struct
  type jumpcloudUser (line 27) | type jumpcloudUser struct
  type jumpcloudApp (line 36) | type jumpcloudApp struct
  function jumpcloudCheckApp (line 40) | func jumpcloudCheckApp(provider *settings.Provider, userId string) (
  function JumpcloudSync (line 97) | func JumpcloudSync(db *database.Database, usr *user.User,

FILE: auth/saml.go
  constant OneLogin (line 18) | OneLogin = "onelogin"
  constant Okta (line 19) | Okta     = "okta"
  function SamlRequest (line 22) | func SamlRequest(db *database.Database, location, query string,

FILE: auth/state.go
  type StateProvider (line 10) | type StateProvider struct
  type StateProviders (line 16) | type StateProviders
    method Len (line 18) | func (s StateProviders) Len() int {
    method Swap (line 22) | func (s StateProviders) Swap(i, j int) {
    method Less (line 26) | func (s StateProviders) Less(i, j int) bool {
  type State (line 30) | type State struct
  function GetState (line 34) | func GetState() (state *State) {
  function GetFastAdminPath (line 73) | func GetFastAdminPath() (path string) {
  function GetFastUserPath (line 106) | func GetFastUserPath() (path string) {

FILE: auth/sync.go
  function SyncUser (line 12) | func SyncUser(db *database.Database, usr *user.User) (

FILE: auth/utils.go
  function Get (line 16) | func Get(db *database.Database, state string) (tokn *Token, err error) {
  function CookieSessionAdmin (line 28) | func CookieSessionAdmin(db *database.Database,
  function CookieSessionUser (line 53) | func CookieSessionUser(db *database.Database, w http.ResponseWriter,
  function CsrfCheck (line 77) | func CsrfCheck(w http.ResponseWriter, r *http.Request, domain string) bo...

FILE: authority/authority.go
  type Authority (line 12) | type Authority struct
    method Validate (line 24) | func (f *Authority) Validate(db *database.Database) (
    method Commit (line 54) | func (f *Authority) Commit(db *database.Database) (err error) {
    method CommitFields (line 65) | func (f *Authority) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 78) | func (f *Authority) Insert(db *database.Database) (err error) {

FILE: authority/constants.go
  constant SshKey (line 6) | SshKey         = "ssh_key"
  constant SshCertificate (line 7) | SshCertificate = "ssh_certificate"

FILE: authority/utils.go
  function Get (line 10) | func Get(db *database.Database, authrId bson.ObjectID) (
  function GetOrg (line 24) | func GetOrg(db *database.Database, orgId, authrId bson.ObjectID) (
  function GetAll (line 42) | func GetAll(db *database.Database, query *bson.M) (
  function GetRoles (line 75) | func GetRoles(db *database.Database, roles []string) (
  function GetMapRoles (line 115) | func GetMapRoles(db *database.Database, query *bson.M) (
  function GetOrgMapRoles (line 154) | func GetOrgMapRoles(db *database.Database, orgId bson.ObjectID) (
  function GetOrgRoles (line 195) | func GetOrgRoles(db *database.Database, orgId bson.ObjectID,
  function GetAllNames (line 231) | func GetAllNames(db *database.Database, query *bson.M) (
  function GetAllPaged (line 274) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 341) | func Remove(db *database.Database, authrId bson.ObjectID) (err error) {
  function RemoveOrg (line 360) | func RemoveOrg(db *database.Database, orgId, authrId bson.ObjectID) (
  function RemoveMulti (line 382) | func RemoveMulti(db *database.Database,
  function RemoveMultiOrg (line 400) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: authorizer/authorizer.go
  type Authorizer (line 13) | type Authorizer struct
    method IsApi (line 21) | func (a *Authorizer) IsApi() bool {
    method IsValid (line 25) | func (a *Authorizer) IsValid() bool {
    method AddSignature (line 29) | func (a *Authorizer) AddSignature(db *database.Database,
    method AddCookie (line 42) | func (a *Authorizer) AddCookie(cook *cookie.Cookie,
    method Clear (line 51) | func (a *Authorizer) Clear(db *database.Database, w http.ResponseWriter,
    method Remove (line 76) | func (a *Authorizer) Remove(db *database.Database) error {
    method GetUser (line 84) | func (a *Authorizer) GetUser(db *database.Database) (
    method GetSession (line 142) | func (a *Authorizer) GetSession() *session.Session {
    method SessionId (line 146) | func (a *Authorizer) SessionId() string {

FILE: authorizer/constants.go
  constant Admin (line 4) | Admin = "admin"
  constant User (line 5) | User  = "user"

FILE: authorizer/utils.go
  function AuthorizeAdmin (line 11) | func AuthorizeAdmin(db *database.Database, w http.ResponseWriter,
  function AuthorizeUser (line 56) | func AuthorizeUser(db *database.Database, w http.ResponseWriter,
  function NewAdmin (line 101) | func NewAdmin() (authr *Authorizer) {
  function NewUser (line 109) | func NewUser() (authr *Authorizer) {

FILE: backup/backup.go
  type Backup (line 26) | type Backup struct
    method backupDisk (line 33) | func (b *Backup) backupDisk(db *database.Database,
    method backupDisks (line 82) | func (b *Backup) backupDisks(db *database.Database) (err error) {
    method backupBackingDisks (line 161) | func (b *Backup) backupBackingDisks(db *database.Database) (err error) {
    method Run (line 257) | func (b *Backup) Run() (err error) {
  function New (line 297) | func New(dest string) *Backup {

FILE: balancer/balancer.go
  type Domain (line 18) | type Domain struct
  type Backend (line 23) | type Backend struct
  type State (line 29) | type State struct
  type Balancer (line 41) | type Balancer struct
    method Validate (line 58) | func (b *Balancer) Validate(db *database.Database) (
    method Json (line 222) | func (b *Balancer) Json() {
    method Clean (line 236) | func (b *Balancer) Clean(db *database.Database) (err error) {
    method CommitState (line 259) | func (b *Balancer) CommitState(db *database.Database, state *State) (
    method Commit (line 278) | func (b *Balancer) Commit(db *database.Database) (err error) {
    method CommitFields (line 289) | func (b *Balancer) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 331) | func (b *Balancer) Insert(db *database.Database) (err error) {

FILE: balancer/constants.go
  constant Http (line 4) | Http = "http"

FILE: balancer/utils.go
  function Get (line 10) | func Get(db *database.Database, balncId bson.ObjectID) (
  function GetOrg (line 24) | func GetOrg(db *database.Database, orgId, balncId bson.ObjectID) (
  function GetAll (line 42) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllPaged (line 75) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 139) | func Remove(db *database.Database, balncId bson.ObjectID) (err error) {
  function RemoveOrg (line 158) | func RemoveOrg(db *database.Database, orgId, balncId bson.ObjectID) (
  function RemoveMulti (line 180) | func RemoveMulti(db *database.Database, balncIds []bson.ObjectID) (
  function RemoveMultiOrg (line 197) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: block/block.go
  type Block (line 18) | type Block struct
    method Validate (line 38) | func (b *Block) Validate(db *database.Database) (
    method Contains (line 198) | func (b *Block) Contains(blckIp *BlockIp) (contains bool, err error) {
    method GetGateway (line 233) | func (b *Block) GetGateway() net.IP {
    method GetGateway6 (line 237) | func (b *Block) GetGateway6() net.IP {
    method GetMask (line 244) | func (b *Block) GetMask() net.IPMask {
    method GetGatewayCidr (line 248) | func (b *Block) GetGatewayCidr() string {
    method GetNetwork (line 259) | func (b *Block) GetNetwork() (staticNet *net.IPNet, err error) {
    method GetIps (line 281) | func (b *Block) GetIps(db *database.Database) (blckIpsSet set.Set, err...
    method GetIpCount (line 303) | func (b *Block) GetIpCount() (count int64, err error) {
    method GetIp (line 386) | func (b *Block) GetIp(db *database.Database,
    method GetIp6 (line 505) | func (b *Block) GetIp6(db *database.Database,
    method RemoveIp (line 575) | func (b *Block) RemoveIp(db *database.Database,
    method ValidateAddresses (line 594) | func (b *Block) ValidateAddresses(db *database.Database,
    method Commit (line 714) | func (b *Block) Commit(db *database.Database) (err error) {
    method CommitFields (line 725) | func (b *Block) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 736) | func (b *Block) Insert(db *database.Database) (err error) {
  type Completion (line 32) | type Completion struct

FILE: block/constants.go
  constant External (line 4) | External = "external"
  constant Host (line 5) | Host     = "host"
  constant NodePort (line 6) | NodePort = "node_port"
  constant IPv4 (line 7) | IPv4     = "ipv4"
  constant IPv6 (line 8) | IPv6     = "ipv6"

FILE: block/errortypes.go
  type BlockFull (line 7) | type BlockFull struct

FILE: block/ip.go
  type BlockIp (line 10) | type BlockIp struct
    method GetIp (line 18) | func (b *BlockIp) GetIp() net.IP {

FILE: block/utils.go
  function GetNodeBlock (line 15) | func GetNodeBlock(ndeId bson.ObjectID) (blck *Block, err error) {
  function GetNodePortBlock (line 42) | func GetNodePortBlock(ndeId bson.ObjectID) (blck *Block, err error) {
  function GetNodePortGateway (line 69) | func GetNodePortGateway() (gateway string, err error) {
  function Get (line 84) | func Get(db *database.Database, blockId bson.ObjectID) (
  function GetAll (line 98) | func GetAll(db *database.Database) (blocks []*Block, err error) {
  function GetInstanceHostIp (line 132) | func GetInstanceHostIp(db *database.Database,
  function GetInstanceNodePortIp (line 154) | func GetInstanceNodePortIp(db *database.Database,
  function GetInstanceIp (line 176) | func GetInstanceIp(db *database.Database, instId bson.ObjectID,
  function GetAllPaged (line 207) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 271) | func Remove(db *database.Database, blockId bson.ObjectID) (err error) {
  function RemoveIp (line 342) | func RemoveIp(db *database.Database, blockIpId bson.ObjectID) (
  function RemoveInstanceIps (line 363) | func RemoveInstanceIps(db *database.Database, instId bson.ObjectID) (
  function RemoveInstanceIpsType (line 384) | func RemoveInstanceIpsType(db *database.Database,
  function RemoveMulti (line 406) | func RemoveMulti(db *database.Database, blckIds []bson.ObjectID) (

FILE: bridges/bridges.go
  function ClearCache (line 24) | func ClearCache() {
  function GetBridges (line 29) | func GetBridges() (brdgs []ip.Interface, err error) {
  function GetIpAddrs (line 112) | func GetIpAddrs(iface string) (addr string, addr6 string, err error) {

FILE: certificate/certificate.go
  type Info (line 21) | type Info struct
  type Certificate (line 31) | type Certificate struct
    method Validate (line 55) | func (c *Certificate) Validate(db *database.Database) (
    method UpdateInfo (line 143) | func (c *Certificate) UpdateInfo() (err error) {
    method Commit (line 208) | func (c *Certificate) Commit(db *database.Database) (err error) {
    method CommitFields (line 219) | func (c *Certificate) CommitFields(db *database.Database, fields set.S...
    method Insert (line 232) | func (c *Certificate) Insert(db *database.Database) (err error) {
    method Hash (line 253) | func (c *Certificate) Hash() string {
  type Completion (line 48) | type Completion struct

FILE: certificate/constants.go
  constant Text (line 6) | Text        = "text"
  constant LetsEncrypt (line 7) | LetsEncrypt = "lets_encrypt"
  constant AcmeHTTP (line 9) | AcmeHTTP = "acme_http"
  constant AcmeDNS (line 10) | AcmeDNS  = "acme_dns"
  constant AcmeAWS (line 12) | AcmeAWS         = "acme_aws"
  constant AcmeCloudflare (line 13) | AcmeCloudflare  = "acme_cloudflare"
  constant AcmeOracleCloud (line 14) | AcmeOracleCloud = "acme_oracle_cloud"
  constant AcmeGoogleCloud (line 15) | AcmeGoogleCloud = "acme_google_cloud"

FILE: certificate/utils.go
  function Get (line 10) | func Get(db *database.Database, certId bson.ObjectID) (
  function GetOrg (line 24) | func GetOrg(db *database.Database, orgId, certId bson.ObjectID) (
  function GetOne (line 42) | func GetOne(db *database.Database, query *bson.M) (cert *Certificate, er...
  function GetAll (line 55) | func GetAll(db *database.Database,
  function GetAllOrg (line 87) | func GetAllOrg(db *database.Database, orgId bson.ObjectID) (
  function GetAllNames (line 121) | func GetAllNames(db *database.Database, query *bson.M) (
  function GetAllPaged (line 160) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 224) | func Remove(db *database.Database, certId bson.ObjectID) (err error) {
  function RemoveOrg (line 238) | func RemoveOrg(db *database.Database, orgId, certId bson.ObjectID) (
  function RemoveMulti (line 260) | func RemoveMulti(db *database.Database, certIds []bson.ObjectID) (
  function RemoveMultiOrg (line 277) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: cloud/cloud.go
  type Subnet (line 3) | type Subnet struct
  type Vpc (line 10) | type Vpc struct

FILE: cloud/oracle.go
  function GetOracleVpcs (line 14) | func GetOracleVpcs(authPv oracle.AuthProvider) (vpcs []*Vpc, err error) {

FILE: cloudinit/cloudinit.go
  constant metaDataTmpl (line 35) | metaDataTmpl = `instance-id: %s
  constant userDataTmpl (line 38) | userDataTmpl = `Content-Type: multipart/mixed; boundary="%s"
  constant netConfigTmpl (line 43) | netConfigTmpl = `version: 1
  constant netConfigLegacyTmpl (line 62) | netConfigLegacyTmpl = `version: 1
  constant netConfig2Tmpl (line 82) | netConfig2Tmpl = `version: 2
  constant netMtu (line 99) | netMtu = `
  constant cloudConfigTmpl (line 102) | cloudConfigTmpl = `#cloud-config
  constant cloudBsdConfigTmpl (line 144) | cloudBsdConfigTmpl = `#cloud-config
  constant deploymentScriptTmpl (line 181) | deploymentScriptTmpl = `#!/bin/sh
  constant deploymentScriptBsdTmpl (line 192) | deploymentScriptBsdTmpl = `#!/bin/sh
  type netConfigData (line 216) | type netConfigData struct
  type cloudConfigData (line 233) | type cloudConfigData struct
  type cloudMount (line 248) | type cloudMount struct
  type imdsConfig (line 256) | type imdsConfig struct
  function getUserData (line 263) | func getUserData(db *database.Database, inst *instance.Instance,
  function getNetData (line 628) | func getNetData(db *database.Database, inst *instance.Instance,
  function Write (line 727) | func Write(db *database.Database, inst *instance.Instance,

FILE: cloudinit/query.go
  type NetworkConfig (line 13) | type NetworkConfig struct
  type NetworkInterface (line 18) | type NetworkInterface struct
  type Subnet (line 28) | type Subnet struct
  type CloudConfig (line 34) | type CloudConfig struct
  type CombinedCloudConfig (line 39) | type CombinedCloudConfig struct
  type MergedSystemConfig (line 43) | type MergedSystemConfig struct
  function GetCloudConfig (line 47) | func GetCloudConfig() (data *CloudConfig, err error) {

FILE: cloudinit/utils.go
  type fileData (line 12) | type fileData struct
  type writeFileData (line 19) | type writeFileData struct
  constant writeFileTmpl (line 23) | writeFileTmpl = `{{range .Files}}
  function generateWriteFiles (line 39) | func generateWriteFiles(filesData []*fileData) (output string, err error) {

FILE: cmd/backup.go
  function Backup (line 13) | func Backup() (err error) {

FILE: cmd/dhcp.go
  function DhcpClient (line 16) | func DhcpClient() (err error) {
  function Dhcp4Server (line 25) | func Dhcp4Server() (err error) {
  function Dhcp6Server (line 49) | func Dhcp6Server() (err error) {
  function NdpServer (line 73) | func NdpServer() (err error) {

FILE: cmd/imds.go
  function ImdsServer (line 7) | func ImdsServer() (err error) {

FILE: cmd/instance.go
  function StartInstance (line 11) | func StartInstance(name string) (err error) {
  function StopInstance (line 36) | func StopInstance(name string) (err error) {

FILE: cmd/log.go
  function ClearLogs (line 9) | func ClearLogs() (err error) {

FILE: cmd/mtu.go
  function MtuCheck (line 7) | func MtuCheck() (err error) {

FILE: cmd/node.go
  function Node (line 25) | func Node() (err error) {

FILE: cmd/optimize.go
  function Optimize (line 8) | func Optimize() (err error) {
  function optimizeNested (line 17) | func optimizeNested() (err error) {

FILE: cmd/settings.go
  function Mongo (line 18) | func Mongo() (err error) {
  function ResetNodeWeb (line 40) | func ResetNodeWeb() (err error) {
  function DefaultPassword (line 83) | func DefaultPassword() (err error) {
  function ResetPassword (line 107) | func ResetPassword() (err error) {
  function DisablePolicies (line 153) | func DisablePolicies() (err error) {
  function DisableFirewall (line 174) | func DisableFirewall() (err error) {
  function SettingsSet (line 211) | func SettingsSet() (err error) {
  function SettingsUnset (line 235) | func SettingsUnset() (err error) {

FILE: colorize/colorize.go
  type Color (line 3) | type Color
  constant None (line 6) | None       = ""
  constant Bold (line 7) | Bold       = "\033[1m"
  constant Black (line 8) | Black      = "\033[0;30m"
  constant BlackBold (line 9) | BlackBold  = "\033[1;30m"
  constant Red (line 10) | Red        = "\033[0;31m"
  constant RedBold (line 11) | RedBold    = "\033[1;31m"
  constant Green (line 12) | Green      = "\033[0;32m"
  constant GreenBold (line 13) | GreenBold  = "\033[1;32m"
  constant Yellow (line 14) | Yellow     = "\033[0;33m"
  constant YellowBold (line 15) | YellowBold = "\033[1;33m"
  constant Blue (line 16) | Blue       = "\033[0;34m"
  constant BlueBold (line 17) | BlueBold   = "\033[1;34m"
  constant Purple (line 18) | Purple     = "\033[0;35m"
  constant PurpleBold (line 19) | PurpleBold = "\033[1;35m"
  constant Cyan (line 20) | Cyan       = "\033[0;36m"
  constant CyanBold (line 21) | CyanBold   = "\033[1;36m"
  constant White (line 22) | White      = "\033[0;37m"
  constant WhiteBold (line 23) | WhiteBold  = "\033[1;37m"
  constant BlackBg (line 24) | BlackBg    = "\033[40m"
  constant RedBg (line 25) | RedBg      = "\033[41m"
  constant GreenBg (line 26) | GreenBg    = "\033[42m"
  constant YellowBg (line 27) | YellowBg   = "\033[43m"
  constant BlueBg (line 28) | BlueBg     = "\033[44m"
  constant PurpleBg (line 29) | PurpleBg   = "\033[45m"
  constant CyanBg (line 30) | CyanBg     = "\033[46m"
  constant WhiteBg (line 31) | WhiteBg    = "\033[47m"
  function ColorString (line 34) | func ColorString(input string, fg Color, bg Color) (str string) {

FILE: completion/completion.go
  type Completion (line 30) | type Completion struct
  type Build (line 53) | type Build struct
  type BuildTag (line 61) | type BuildTag struct
  function get (line 66) | func get(db *database.Database, coll *database.Collection,
  function GetCompletion (line 97) | func GetCompletion(db *database.Database, orgId bson.ObjectID,

FILE: compositor/compositor.go
  constant ProcDir (line 18) | ProcDir = "/proc"
  function GetEnv (line 21) | func GetEnv(username, driPath string, driPrime bool) (

FILE: config/config.go
  type ConfigData (line 26) | type ConfigData struct
    method Save (line 33) | func (c *ConfigData) Save() (err error) {
  function Load (line 65) | func Load() (err error) {
  function Save (line 112) | func Save() (err error) {
  function GetModTime (line 121) | func GetModTime() (mod time.Time, err error) {
  function init (line 135) | func init() {

FILE: constants/constants.go
  constant Version (line 8) | Version         = "2.0.3665.99"
  constant DatabaseVersion (line 9) | DatabaseVersion = 1
  constant LogPath (line 10) | LogPath         = "/var/log/pritunl-cloud.log"
  constant LogPath2 (line 11) | LogPath2        = "/var/log/pritunl-cloud.log.1"
  constant StaticCache (line 12) | StaticCache     = true
  constant RetryDelay (line 13) | RetryDelay      = 3 * time.Second

FILE: cookie/cookie.go
  type Cookie (line 23) | type Cookie struct
    method Get (line 30) | func (c *Cookie) Get(key string) string {
    method Set (line 38) | func (c *Cookie) Set(key string, val string) {
    method GetSession (line 42) | func (c *Cookie) GetSession(db *database.Database, r *http.Request,
    method NewSession (line 79) | func (c *Cookie) NewSession(db *database.Database, r *http.Request,
    method Remove (line 112) | func (c *Cookie) Remove(db *database.Database) (err error) {
    method Save (line 139) | func (c *Cookie) Save() (err error) {
  function init (line 144) | func init() {

FILE: cookie/utils.go
  function GetAdmin (line 11) | func GetAdmin(w http.ResponseWriter, r *http.Request) (
  function NewAdmin (line 32) | func NewAdmin(w http.ResponseWriter, r *http.Request) (cook *Cookie) {
  function CleanAdmin (line 44) | func CleanAdmin(w http.ResponseWriter, r *http.Request) {
  function GetUser (line 57) | func GetUser(w http.ResponseWriter, r *http.Request) (
  function NewUser (line 78) | func NewUser(w http.ResponseWriter, r *http.Request) (cook *Cookie) {
  function CleanUser (line 90) | func CleanUser(w http.ResponseWriter, r *http.Request) {

FILE: crypto/crypto.go
  type Message (line 18) | type Message struct
  type AsymNaclHmacKey (line 24) | type AsymNaclHmacKey struct
  type AsymNaclHmac (line 31) | type AsymNaclHmac struct
    method RegisterNonce (line 39) | func (a *AsymNaclHmac) RegisterNonce(handler func(nonce []byte) error) {
    method Seal (line 43) | func (a *AsymNaclHmac) Seal(input any) (msg *Message, err error) {
    method SealJson (line 87) | func (a *AsymNaclHmac) SealJson(input any) (output string, err error) {
    method Unseal (line 105) | func (a *AsymNaclHmac) Unseal(msg *Message, output any) (err error) {
    method UnsealJson (line 188) | func (a *AsymNaclHmac) UnsealJson(input string, output any) (err error) {
    method Export (line 207) | func (a *AsymNaclHmac) Export() AsymNaclHmacKey {
    method Import (line 216) | func (a *AsymNaclHmac) Import(key AsymNaclHmacKey) (err error) {
    method Generate (line 303) | func (a *AsymNaclHmac) Generate() (err error) {

FILE: csrf/csrf.go
  type CsrfToken (line 10) | type CsrfToken struct
  function NewToken (line 16) | func NewToken(db *database.Database, sessionId string) (
  function ValidateToken (line 42) | func ValidateToken(db *database.Database, sessionId, token string) (

FILE: data/disk.go
  function createDiskQcow (line 16) | func createDiskQcow(db *database.Database, dsk *disk.Disk) (
  function createDiskLvm (line 47) | func createDiskLvm(db *database.Database, dsk *disk.Disk) (
  function CreateDisk (line 80) | func CreateDisk(db *database.Database, dsk *disk.Disk) (
  function ActivateDisk (line 106) | func ActivateDisk(db *database.Database, dsk *disk.Disk) (err error) {
  function DeactivateDisk (line 127) | func DeactivateDisk(db *database.Database, dsk *disk.Disk) (err error) {

FILE: data/image.go
  function getImageS3 (line 51) | func getImageS3(db *database.Database, store *storage.Storage,
  type ProgressS3 (line 112) | type ProgressS3 struct
    method Start (line 144) | func (p *ProgressS3) Start() {
    method Stop (line 161) | func (p *ProgressS3) Stop() {
    method calculateProgress (line 168) | func (p *ProgressS3) calculateProgress() {
    method syncProgress (line 189) | func (p *ProgressS3) syncProgress() {
  function NewProgressS3 (line 127) | func NewProgressS3(db *database.Database, dsk *disk.Disk, img *image.Image,
  type Progress (line 214) | type Progress struct
    method Write (line 238) | func (p *Progress) Write(data []byte) (n int, err error) {
  function humanReadableSpeed (line 225) | func humanReadableSpeed(bytesPerSecond float64) string {
  function getImageWeb (line 262) | func getImageWeb(db *database.Database, store *storage.Storage,
  function checkImageSigS3 (line 350) | func checkImageSigS3(db *database.Database, store *storage.Storage,
  function checkImageSigWeb (line 425) | func checkImageSigWeb(db *database.Database, store *storage.Storage,
  function getImage (line 499) | func getImage(db *database.Database, dsk *disk.Disk, img *image.Image,
  function copyBackingImage (line 596) | func copyBackingImage(imagePth, backingImagePth string) (err error) {
  function writeFsQcow (line 617) | func writeFsQcow(db *database.Database, dsk *disk.Disk) (err error) {
  function writeImageQcow (line 786) | func writeImageQcow(db *database.Database, dsk *disk.Disk) (
  function writeFsLvm (line 1045) | func writeFsLvm(db *database.Database, dsk *disk.Disk,
  function writeImageLvm (line 1205) | func writeImageLvm(db *database.Database, dsk *disk.Disk,
  function DeleteImage (line 1317) | func DeleteImage(db *database.Database, imgId bson.ObjectID) (
  function WriteImage (line 1359) | func WriteImage(db *database.Database, dsk *disk.Disk) (
  function DeleteImages (line 1396) | func DeleteImages(db *database.Database, imgIds []bson.ObjectID) (
  function DeleteImageOrg (line 1409) | func DeleteImageOrg(db *database.Database, orgId, imgId bson.ObjectID) (
  function DeleteImagesOrg (line 1451) | func DeleteImagesOrg(db *database.Database, orgId bson.ObjectID,
  function CreateSnapshot (line 1464) | func CreateSnapshot(db *database.Database, dsk *disk.Disk,
  function CreateBackup (line 1665) | func CreateBackup(db *database.Database, dsk *disk.Disk,
  function RestoreBackup (line 1845) | func RestoreBackup(db *database.Database, dsk *disk.Disk) (err error) {
  function ImageAvailable (line 1950) | func ImageAvailable(store *storage.Storage, img *image.Image) (

FILE: data/resize.go
  type diskInfo (line 19) | type diskInfo struct
  function getQcowSize (line 26) | func getQcowSize(pth string) (size int, err error) {
  function getDiskSizeQcow (line 48) | func getDiskSizeQcow(dsk *disk.Disk) (size int, err error) {
  function expandDiskQcow (line 52) | func expandDiskQcow(db *database.Database, dsk *disk.Disk) (err error) {
  function expandDiskLvm (line 94) | func expandDiskLvm(db *database.Database, dsk *disk.Disk) (err error) {
  function ExpandDisk (line 176) | func ExpandDisk(db *database.Database, dsk *disk.Disk) (err error) {

FILE: data/sync.go
  function getImagesS3 (line 43) | func getImagesS3(db *database.Database, store *storage.Storage) (
  type Files (line 112) | type Files struct
  type File (line 117) | type File struct
  function getImagesWeb (line 124) | func getImagesWeb(db *database.Database, store *storage.Storage) (
  function Sync (line 190) | func Sync(db *database.Database, store *storage.Storage) (err error) {

FILE: data/utils.go
  function GetVgName (line 12) | func GetVgName(id bson.ObjectID, n int) string {
  function GetLvName (line 19) | func GetLvName(id bson.ObjectID, n int) string {

FILE: database/base.go
  type Named (line 7) | type Named struct

FILE: database/client.go
  function getClient (line 19) | func getClient() *mongo.Client {
  function setClient (line 27) | func setClient(client *mongo.Client) {

FILE: database/collection.go
  type Collection (line 14) | type Collection struct
    method FindOneId (line 19) | func (c *Collection) FindOneId(id interface{}, data interface{}) (err ...
    method UpdateId (line 31) | func (c *Collection) UpdateId(id interface{}, data interface{}) (err e...
    method Commit (line 43) | func (c *Collection) Commit(id interface{}, data interface{}) (err err...
    method CommitFields (line 57) | func (c *Collection) CommitFields(id interface{}, data interface{},
    method Upsert (line 71) | func (c *Collection) Upsert(query *bson.M, data interface{}) (err erro...
  function SelectFields (line 83) | func SelectFields(obj interface{}, fields set.Set) (data bson.M) {
  function SelectFieldsAll (line 167) | func SelectFieldsAll(obj interface{}, fields set.Set) (data bson.M) {
  type ArraySelectFields (line 273) | type ArraySelectFields struct
    method Modified (line 285) | func (a *ArraySelectFields) Modified() bool {
    method Update (line 289) | func (a *ArraySelectFields) Update(docId bson.ObjectID,
    method Push (line 308) | func (a *ArraySelectFields) Push(doc interface{}) {
    method Delete (line 313) | func (a *ArraySelectFields) Delete(docId bson.ObjectID) {
    method GetQuery (line 318) | func (a *ArraySelectFields) GetQuery() (query bson.M, filters []interf...
  function NewArraySelectFields (line 350) | func NewArraySelectFields(obj interface{}, rootKey string, fields set.Se...

FILE: database/database.go
  type Database (line 21) | type Database struct
    method Deadline (line 27) | func (d *Database) Deadline() (time.Time, bool) {
    method Done (line 34) | func (d *Database) Done() <-chan struct{} {
    method Err (line 41) | func (d *Database) Err() error {
    method Value (line 48) | func (d *Database) Value(key interface{}) interface{} {
    method String (line 55) | func (d *Database) String() string {
    method Close (line 59) | func (d *Database) Close() {
    method GetCollection (line 62) | func (d *Database) GetCollection(name string) (coll *Collection) {
    method getCollectionWeak (line 70) | func (d *Database) getCollectionWeak(name string) (coll *Collection) {
    method getCollectionStrong (line 82) | func (d *Database) getCollectionStrong(name string) (coll *Collection) {
    method Users (line 94) | func (d *Database) Users() (coll *Collection) {
    method Policies (line 99) | func (d *Database) Policies() (coll *Collection) {
    method Devices (line 104) | func (d *Database) Devices() (coll *Collection) {
    method Alerts (line 109) | func (d *Database) Alerts() (coll *Collection) {
    method AlertsEvent (line 114) | func (d *Database) AlertsEvent() (coll *Collection) {
    method AlertsEventLock (line 119) | func (d *Database) AlertsEventLock() (coll *Collection) {
    method Pods (line 124) | func (d *Database) Pods() (coll *Collection) {
    method Units (line 129) | func (d *Database) Units() (coll *Collection) {
    method Specs (line 134) | func (d *Database) Specs() (coll *Collection) {
    method Deployments (line 139) | func (d *Database) Deployments() (coll *Collection) {
    method Sessions (line 144) | func (d *Database) Sessions() (coll *Collection) {
    method Tasks (line 149) | func (d *Database) Tasks() (coll *Collection) {
    method Tokens (line 154) | func (d *Database) Tokens() (coll *Collection) {
    method CsrfTokens (line 159) | func (d *Database) CsrfTokens() (coll *Collection) {
    method SecondaryTokens (line 164) | func (d *Database) SecondaryTokens() (coll *Collection) {
    method Nonces (line 169) | func (d *Database) Nonces() (coll *Collection) {
    method Rokeys (line 174) | func (d *Database) Rokeys() (coll *Collection) {
    method Schedulers (line 179) | func (d *Database) Schedulers() (coll *Collection) {
    method Settings (line 184) | func (d *Database) Settings() (coll *Collection) {
    method Events (line 189) | func (d *Database) Events() (coll *Collection) {
    method Nodes (line 194) | func (d *Database) Nodes() (coll *Collection) {
    method NodePorts (line 199) | func (d *Database) NodePorts() (coll *Collection) {
    method Organizations (line 204) | func (d *Database) Organizations() (coll *Collection) {
    method Storages (line 209) | func (d *Database) Storages() (coll *Collection) {
    method Images (line 214) | func (d *Database) Images() (coll *Collection) {
    method Datacenters (line 219) | func (d *Database) Datacenters() (coll *Collection) {
    method Zones (line 224) | func (d *Database) Zones() (coll *Collection) {
    method Shapes (line 229) | func (d *Database) Shapes() (coll *Collection) {
    method Balancers (line 234) | func (d *Database) Balancers() (coll *Collection) {
    method Advisories (line 239) | func (d *Database) Advisories() (coll *Collection) {
    method Instances (line 244) | func (d *Database) Instances() (coll *Collection) {
    method Pools (line 249) | func (d *Database) Pools() (coll *Collection) {
    method Disks (line 254) | func (d *Database) Disks() (coll *Collection) {
    method Blocks (line 259) | func (d *Database) Blocks() (coll *Collection) {
    method BlocksIp (line 264) | func (d *Database) BlocksIp() (coll *Collection) {
    method LvmLock (line 269) | func (d *Database) LvmLock() (coll *Collection) {
    method Journal (line 274) | func (d *Database) Journal() (coll *Collection) {
    method Firewalls (line 279) | func (d *Database) Firewalls() (coll *Collection) {
    method Versions (line 284) | func (d *Database) Versions() (coll *Collection) {
    method Plans (line 289) | func (d *Database) Plans() (coll *Collection) {
    method Vpcs (line 294) | func (d *Database) Vpcs() (coll *Collection) {
    method VpcsIp (line 299) | func (d *Database) VpcsIp() (coll *Collection) {
    method Authorities (line 304) | func (d *Database) Authorities() (coll *Collection) {
    method Certificates (line 309) | func (d *Database) Certificates() (coll *Collection) {
    method Secrets (line 314) | func (d *Database) Secrets() (coll *Collection) {
    method Domains (line 319) | func (d *Database) Domains() (coll *Collection) {
    method DomainsRecords (line 324) | func (d *Database) DomainsRecords() (coll *Collection) {
    method AcmeChallenges (line 329) | func (d *Database) AcmeChallenges() (coll *Collection) {
    method Logs (line 334) | func (d *Database) Logs() (coll *Collection) {
    method Audits (line 339) | func (d *Database) Audits() (coll *Collection) {
    method Geo (line 344) | func (d *Database) Geo() (coll *Collection) {
  function Connect (line 349) | func Connect() (err error) {
  function ValidateDatabase (line 413) | func ValidateDatabase() (version string, err error) {
  function getDatabase (line 469) | func getDatabase(ctx context.Context, client *mongo.Client) *Database {
  function GetDatabase (line 483) | func GetDatabase() *Database {
  function GetDatabaseCtx (line 487) | func GetDatabaseCtx(ctx context.Context) *Database {
  function addIndexes (line 491) | func addIndexes() (err error) {
  function addCollections (line 1347) | func addCollections() (err error) {
  function init (line 1422) | func init() {

FILE: database/errors.go
  type ConnectionError (line 7) | type ConnectionError struct
  type IndexError (line 11) | type IndexError struct
  type NotFoundError (line 15) | type NotFoundError struct
  type ImmutableKeyError (line 19) | type ImmutableKeyError struct
  type DuplicateKeyError (line 23) | type DuplicateKeyError struct
  type UnknownError (line 27) | type UnknownError struct
  type CertificateError (line 31) | type CertificateError struct
  type IndexConflict (line 35) | type IndexConflict struct

FILE: database/index.go
  type bsonIndex (line 23) | type bsonIndex struct
  type Index (line 27) | type Index struct
    method Create (line 94) | func (i *Index) Create() (err error) {
  function GenerateIndexName (line 35) | func GenerateIndexName(doc bson.D) (indexName string, err error) {
  function CleanIndexes (line 164) | func CleanIndexes(db *Database) (err error) {

FILE: database/utils.go
  function FindProject (line 13) | func FindProject(fields ...string) *options.FindOptionsBuilder {
  function FindOneProject (line 26) | func FindOneProject(fields ...string) *options.FindOneOptionsBuilder {
  function GetErrorCodes (line 39) | func GetErrorCodes(err error) (errCodes []int) {
  function ParseError (line 99) | func ParseError(err error) (newErr error) {
  function IgnoreNotFoundError (line 135) | func IgnoreNotFoundError(err error) (newErr error) {

FILE: datacenter/constants.go
  constant Default (line 4) | Default     = "default"
  constant VxlanVlan (line 5) | VxlanVlan   = "vxlan_vlan"
  constant WgVxlanVlan (line 6) | WgVxlanVlan = "wg_vxlan_vlan"
  constant Wg4 (line 8) | Wg4 = "wg4"
  constant Wg6 (line 9) | Wg6 = "wg6"

FILE: datacenter/datacenter.go
  type Datacenter (line 14) | type Datacenter struct
    method Validate (line 36) | func (d *Datacenter) Validate(db *database.Database) (
    method Vxlan (line 98) | func (d *Datacenter) Vxlan() bool {
    method GetBaseInternalMtu (line 102) | func (d *Datacenter) GetBaseInternalMtu() (mtuSize int) {
    method GetBaseExternalMtu (line 115) | func (d *Datacenter) GetBaseExternalMtu() (mtuSize int) {
    method GetOverlayMtu (line 128) | func (d *Datacenter) GetOverlayMtu() (mtuSize int) {
    method GetInstanceMtu (line 164) | func (d *Datacenter) GetInstanceMtu() (mtuSize int) {
    method Commit (line 200) | func (d *Datacenter) Commit(db *database.Database) (err error) {
    method CommitFields (line 211) | func (d *Datacenter) CommitFields(db *database.Database, fields set.Se...
    method Insert (line 224) | func (d *Datacenter) Insert(db *database.Database) (err error) {
  type Completion (line 30) | type Completion struct

FILE: datacenter/utils.go
  function Get (line 10) | func Get(db *database.Database, dcId bson.ObjectID) (
  function ExistsOrg (line 24) | func ExistsOrg(db *database.Database, orgId, dcId bson.ObjectID) (
  function GetAll (line 52) | func GetAll(db *database.Database) (dcs []*Datacenter, err error) {
  function GetOne (line 83) | func GetOne(db *database.Database, query *bson.M) (dc *Datacenter, err e...
  function GetAllNamesOrg (line 96) | func GetAllNamesOrg(db *database.Database, orgId bson.ObjectID) (
  function GetAllNames (line 144) | func GetAllNames(db *database.Database, query *bson.M) (
  function GetAllPaged (line 186) | func GetAllPaged(db *database.Database, query *bson.M,
  function DistinctOrg (line 250) | func DistinctOrg(db *database.Database, orgId bson.ObjectID) (
  function Remove (line 274) | func Remove(db *database.Database, dcId bson.ObjectID) (err error) {
  function RemoveMulti (line 293) | func RemoveMulti(db *database.Database, dcIds []bson.ObjectID) (
  function RemoveMultiOrg (line 310) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: defaults/defaults.go
  function initStorage (line 31) | func initStorage(db *database.Database) (err error) {
  function initOrganization (line 77) | func initOrganization(db *database.Database) (
  function initDatacenter (line 130) | func initDatacenter(db *database.Database) (
  function initZone (line 200) | func initZone(db *database.Database, defaultDc bson.ObjectID) (
  function initVpc (line 245) | func initVpc(db *database.Database, defaultOrg,
  function initFirewall (line 313) | func initFirewall(db *database.Database, defaultOrg bson.ObjectID) (
  function initAuthority (line 505) | func initAuthority(db *database.Database, defaultOrg bson.ObjectID) (
  function initNode (line 558) | func initNode(db *database.Database, defaultOrg bson.ObjectID) (
  function Defaults (line 835) | func Defaults() (err error) {

FILE: demo/demo.go
  function IsDemo (line 9) | func IsDemo() bool {
  function Blocked (line 13) | func Blocked(c *gin.Context) bool {
  function BlockedSilent (line 27) | func BlockedSilent(c *gin.Context) bool {

FILE: demo/rand.go
  function RandIp (line 18) | func RandIp(instId bson.ObjectID) (addr string) {
  function RandIp6 (line 31) | func RandIp6(instId bson.ObjectID) (addr string) {
  function RandPrivateIp (line 44) | func RandPrivateIp(instId bson.ObjectID) (addr string) {
  function RandPrivateIp6 (line 57) | func RandPrivateIp6(instId bson.ObjectID) (addr string) {

FILE: deploy/deploy.go
  function Deploy (line 10) | func Deploy(stat *state.State, runtimes *state.Runtimes) (err error) {

FILE: deploy/deployments.go
  type Deployments (line 33) | type Deployments struct
    method migrate (line 37) | func (d *Deployments) migrate(deply *deployment.Deployment) {
    method destroy (line 362) | func (d *Deployments) destroy(deply *deployment.Deployment) {
    method archive (line 467) | func (d *Deployments) archive(deply *deployment.Deployment) (err error) {
    method restore (line 552) | func (d *Deployments) restore(deply *deployment.Deployment) (err error) {
    method imageShutdown (line 715) | func (d *Deployments) imageShutdown(db *database.Database,
    method image (line 760) | func (d *Deployments) image(deply *deployment.Deployment) (err error) {
    method domainCommit (line 845) | func (d *Deployments) domainCommit(deply *deployment.Deployment,
    method domain (line 934) | func (d *Deployments) domain(db *database.Database,
    method Deploy (line 1150) | func (d *Deployments) Deploy(db *database.Database) (err error) {
  function NewDeployments (line 1206) | func NewDeployments(stat *state.State) *Deployments {

FILE: deploy/disks.go
  type Disks (line 27) | type Disks struct
    method provision (line 31) | func (d *Disks) provision(dsk *disk.Disk) {
    method snapshot (line 83) | func (d *Disks) snapshot(dsk *disk.Disk) {
    method expand (line 150) | func (d *Disks) expand(dsk *disk.Disk) {
    method backup (line 226) | func (d *Disks) backup(dsk *disk.Disk) {
    method restore (line 301) | func (d *Disks) restore(dsk *disk.Disk) {
    method destroy (line 394) | func (d *Disks) destroy(db *database.Database, dsk *disk.Disk) {
    method scheduleBackup (line 467) | func (d *Disks) scheduleBackup(dsk *disk.Disk) {
    method Deploy (line 551) | func (d *Disks) Deploy(db *database.Database) (err error) {
  function NewDisks (line 594) | func NewDisks(stat *state.State) *Disks {

FILE: deploy/imds.go
  type Imds (line 23) | type Imds struct
    method buildInstance (line 27) | func (s *Imds) buildInstance(db *database.Database,
    method buildDeployInstance (line 60) | func (s *Imds) buildDeployInstance(db *database.Database,
    method Deploy (line 156) | func (s *Imds) Deploy(db *database.Database) (err error) {
  function NewImds (line 197) | func NewImds(stat *state.State) *Imds {

FILE: deploy/instances.go
  type Instances (line 41) | type Instances struct
    method create (line 45) | func (s *Instances) create(inst *instance.Instance) {
    method start (line 94) | func (s *Instances) start(inst *instance.Instance) {
    method cleanup (line 156) | func (s *Instances) cleanup(inst *instance.Instance) {
    method stop (line 193) | func (s *Instances) stop(inst *instance.Instance) {
    method restart (line 228) | func (s *Instances) restart(inst *instance.Instance) {
    method destroy (line 311) | func (s *Instances) destroy(inst *instance.Instance) {
    method diskAdd (line 377) | func (s *Instances) diskAdd(inst *instance.Instance,
    method diskRemove (line 435) | func (s *Instances) diskRemove(inst *instance.Instance,
    method usbAdd (line 488) | func (s *Instances) usbAdd(inst *instance.Instance, virt *vm.VirtualMa...
    method usbRemove (line 541) | func (s *Instances) usbRemove(inst *instance.Instance,
    method diff (line 594) | func (s *Instances) diff(db *database.Database,
    method check (line 653) | func (s *Instances) check(inst *instance.Instance, namespaces set.Set) (
    method routes (line 670) | func (s *Instances) routes(inst *instance.Instance) (err error) {
    method Deploy (line 886) | func (s *Instances) Deploy(db *database.Database) (err error) {
  function NewInstances (line 1076) | func NewInstances(stat *state.State) *Instances {

FILE: deploy/ipset.go
  type Ipset (line 8) | type Ipset struct
    method Deploy (line 12) | func (t *Ipset) Deploy() (err error) {
    method Clean (line 26) | func (t *Ipset) Clean() (err error) {
  function NewIpset (line 39) | func NewIpset(stat *state.State) *Ipset {

FILE: deploy/iptables.go
  type Iptables (line 8) | type Iptables struct
    method Deploy (line 12) | func (t *Iptables) Deploy() (err error) {
  function NewIptables (line 27) | func NewIptables(stat *state.State) *Iptables {

FILE: deploy/namespace.go
  type Namespace (line 22) | type Namespace struct
    method Deploy (line 26) | func (n *Namespace) Deploy(db *database.Database) (err error) {
  function NewNamespace (line 114) | func NewNamespace(stat *state.State) *Namespace {

FILE: deploy/network.go
  type Network (line 24) | type Network struct
    method Deploy (line 28) | func (d *Network) Deploy() (err error) {
  function NewNetwork (line 49) | func NewNetwork(stat *state.State) *Network {
  function nodePortCreate (line 55) | func nodePortCreate() (err error) {
  function nodePortGetAddr (line 75) | func nodePortGetAddr() (addr string, err error) {
  function nodePortSetAddr (line 89) | func nodePortSetAddr(addr string) (err error) {
  function nodePortClearAddr (line 120) | func nodePortClearAddr() (err error) {
  function nodePortRemoveNetwork (line 142) | func nodePortRemoveNetwork(stat *state.State) (err error) {
  function NodePortApplyState (line 157) | func NodePortApplyState(stat *state.State) (err error) {

FILE: deploy/services.go
  type Pods (line 28) | type Pods struct
    method processSchedule (line 32) | func (s *Pods) processSchedule(schd *scheduler.Scheduler) {
    method deploySchedule (line 60) | func (s *Pods) deploySchedule(schd *scheduler.Scheduler) (err error) {
    method DeploySpec (line 174) | func (s *Pods) DeploySpec(db *database.Database,
    method Deploy (line 491) | func (s *Pods) Deploy(db *database.Database) (err error) {
  function NewPods (line 530) | func NewPods(stat *state.State) *Pods {

FILE: deployment/constants.go
  constant Provision (line 10) | Provision = "provision"
  constant Reserved (line 11) | Reserved  = "reserved"
  constant Deployed (line 12) | Deployed  = "deployed"
  constant Archived (line 13) | Archived  = "archived"
  constant Destroy (line 15) | Destroy = "destroy"
  constant Archive (line 16) | Archive = "archive"
  constant Migrate (line 17) | Migrate = "migrate"
  constant Restore (line 18) | Restore = "restore"
  constant Ready (line 20) | Ready    = "ready"
  constant Snapshot (line 21) | Snapshot = "snapshot"
  constant Complete (line 22) | Complete = "complete"
  constant Failed (line 23) | Failed   = "failed"
  constant Instance (line 25) | Instance = "instance"
  constant Image (line 26) | Image    = "image"
  constant Firewall (line 27) | Firewall = "firewall"
  constant Domain (line 28) | Domain   = "domain"
  constant Healthy (line 30) | Healthy   = "healthy"
  constant Unknown (line 31) | Unknown   = "unknown"
  constant Unhealthy (line 32) | Unhealthy = "unhealthy"
  constant ThresholdMin (line 34) | ThresholdMin = 10
  constant ActionLimit (line 35) | ActionLimit  = 1 * time.Minute

FILE: deployment/deployment.go
  type Deployment (line 14) | type Deployment struct
    method IsHealthy (line 83) | func (d *Deployment) IsHealthy() bool {
    method Validate (line 87) | func (d *Deployment) Validate(db *database.Database) (
    method HandleStatement (line 163) | func (d *Deployment) HandleStatement(db *database.Database,
    method SetImageState (line 244) | func (d *Deployment) SetImageState(state string) {
    method GetImageState (line 251) | func (d *Deployment) GetImageState() string {
    method ImageReady (line 258) | func (d *Deployment) ImageReady() bool {
    method CommitAction (line 263) | func (d *Deployment) CommitAction(db *database.Database,
    method RemoveAction (line 283) | func (d *Deployment) RemoveAction(db *database.Database,
    method Commit (line 303) | func (d *Deployment) Commit(db *database.Database) (err error) {
    method CommitFields (line 314) | func (d *Deployment) CommitFields(db *database.Database, fields set.Se...
    method Insert (line 327) | func (d *Deployment) Insert(db *database.Database) (err error) {
  type InstanceData (line 40) | type InstanceData struct
  type DomainData (line 51) | type DomainData struct
  type RecordData (line 55) | type RecordData struct
  type ImageData (line 60) | type ImageData struct
  type Mount (line 64) | type Mount struct
  type Journal (line 70) | type Journal struct
  type Action (line 76) | type Action struct

FILE: deployment/utils.go
  function Get (line 13) | func Get(db *database.Database, deplyId bson.ObjectID) (
  function GetUnit (line 27) | func GetUnit(db *database.Database, unitId, deplyId bson.ObjectID) (
  function GetOrg (line 45) | func GetOrg(db *database.Database, orgId, unitId bson.ObjectID) (
  function GetUnitOrg (line 63) | func GetUnitOrg(db *database.Database,
  function GetAll (line 83) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllSorted (line 116) | func GetAllSorted(db *database.Database, query *bson.M) (
  function GetAllActiveIds (line 156) | func GetAllActiveIds(db *database.Database) (deplyIds set.Set, err error) {
  function GetAllStates (line 201) | func GetAllStates(db *database.Database) (
  function RemoveDomains (line 243) | func RemoveDomains(db *database.Database, deplyId bson.ObjectID) (
  function Remove (line 304) | func Remove(db *database.Database, deplyId bson.ObjectID) (err error) {
  function RemoveMulti (line 335) | func RemoveMulti(db *database.Database, unitId bson.ObjectID,
  function ArchiveMulti (line 358) | func ArchiveMulti(db *database.Database, unitId bson.ObjectID,
  function RestoreMulti (line 382) | func RestoreMulti(db *database.Database, unitId bson.ObjectID,

FILE: device/constants.go
  constant U2f (line 4) | U2f       = "u2f"
  constant WebAuthn (line 5) | WebAuthn  = "webauthn"
  constant Secondary (line 6) | Secondary = "secondary"
  constant Phone (line 7) | Phone     = "phone"
  constant Call (line 8) | Call      = "call"
  constant Message (line 9) | Message   = "message"
  constant Low (line 10) | Low       = 1
  constant Medium (line 11) | Medium    = 5
  constant High (line 12) | High      = 10

FILE: device/device.go
  type Device (line 18) | type Device struct
    method Validate (line 41) | func (d *Device) Validate(db *database.Database) (
    method SetActive (line 121) | func (d *Device) SetActive(db *database.Database) (err error) {
    method MarshalWebauthn (line 131) | func (d *Device) MarshalWebauthn(cred *webauthn.Credential) {
    method UnmarshalWebauthn (line 144) | func (d *Device) UnmarshalWebauthn() (cred webauthn.Credential, err er...
    method CheckLevel (line 185) | func (d *Device) CheckLevel(level int) bool {
    method Commit (line 199) | func (d *Device) Commit(db *database.Database) (err error) {
    method CommitFields (line 210) | func (d *Device) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 223) | func (d *Device) Insert(db *database.Database) (err error) {

FILE: device/facet.go
  type FacetVersion (line 7) | type FacetVersion struct
  type TrustedFacet (line 12) | type TrustedFacet struct
  type Facets (line 17) | type Facets struct
  function GetFacets (line 21) | func GetFacets() (facets *Facets) {

FILE: device/utils.go
  function Get (line 11) | func Get(db *database.Database, devcId bson.ObjectID) (
  function GetUser (line 25) | func GetUser(db *database.Database, devcId bson.ObjectID,
  function GetAll (line 43) | func GetAll(db *database.Database, userId bson.ObjectID) (
  function GetAllSorted (line 78) | func GetAllSorted(db *database.Database, userId bson.ObjectID) (
  function GetAllMode (line 118) | func GetAllMode(db *database.Database, userId bson.ObjectID,
  function CountSecondary (line 154) | func CountSecondary(db *database.Database, userId bson.ObjectID) (
  function New (line 171) | func New(userId bson.ObjectID, typ, mode string) (devc *Device) {
  function Remove (line 184) | func Remove(db *database.Database, id bson.ObjectID) (err error) {
  function RemoveUser (line 204) | func RemoveUser(db *database.Database, id bson.ObjectID,
  function RemoveAll (line 227) | func RemoveAll(db *database.Database, userId bson.ObjectID) (err error) {

FILE: dhcpc/constants.go
  constant MaxMessageSize (line 8) | MaxMessageSize  = 1500
  constant DefaultInterval (line 9) | DefaultInterval = 60 * time.Second
  constant DhcpTimeout (line 10) | DhcpTimeout     = 10 * time.Second
  constant DhcpRetries (line 11) | DhcpRetries     = 3

FILE: dhcpc/dhcpc.go
  type Dhcpc (line 16) | type Dhcpc struct
    method startSync (line 29) | func (d *Dhcpc) startSync() {
    method sync (line 64) | func (d *Dhcpc) sync() {
    method run4 (line 71) | func (d *Dhcpc) run4() (err error) {
    method run6 (line 171) | func (d *Dhcpc) run6() (err error) {
    method Run (line 270) | func (d *Dhcpc) Run(ip4, ip6 bool) {
  function Main (line 324) | func Main() (err error) {

FILE: dhcpc/imds.go
  type SyncData (line 23) | type SyncData struct
  type Imds (line 30) | type Imds struct
    method NewRequest (line 36) | func (m *Imds) NewRequest(method, pth string, data interface{}) (
    method Sync (line 75) | func (m *Imds) Sync(lease *Lease) (err error) {

FILE: dhcpc/lease.go
  type Lease (line 10) | type Lease struct
    method IfaceReady (line 28) | func (l *Lease) IfaceReady() (ready4, ready6 bool) {

FILE: dhcpc/lease4.go
  method Renew4 (line 13) | func (l *Lease) Renew4() (ok bool, err error) {
  method Exchange4 (line 82) | func (l *Lease) Exchange4() (ok bool, err error) {

FILE: dhcpc/lease6.go
  method Renew6 (line 14) | func (l *Lease) Renew6() (ok bool, err error) {
  method Exchange6 (line 121) | func (l *Lease) Exchange6() (ok bool, err error) {
  function extractDhcpv6Lease (line 200) | func extractDhcpv6Lease(reply *dhcpv6.Message, ifaceName string) *Lease {

FILE: dhcpc/systemd.go
  constant systemdNamespaceTemplate (line 21) | systemdNamespaceTemplate = `[Unit]
  constant systemdTemplate (line 49) | systemdTemplate = `[Unit]
  function WriteService (line 76) | func WriteService(vmId bson.ObjectID,
  function Start (line 144) | func Start(db *database.Database, virt *vm.VirtualMachine,
  function Stop (line 178) | func Stop(virt *vm.VirtualMachine) (err error) {

FILE: dhcpc/utils.go
  function buildDhLease (line 13) | func buildDhLease(lease *Lease, addr net.HardwareAddr) (
  function extractDhLease (line 66) | func extractDhLease(dhLease *nclient4.Lease) (lease *Lease) {
  function TransactionIdUnmarshal (line 106) | func TransactionIdUnmarshal(str string) dhcpv4.TransactionID {

FILE: dhcps/dhcp4.go
  type Server4 (line 15) | type Server4 struct
    method handler (line 29) | func (s *Server4) handler(conn net.PacketConn, peer net.Addr,
    method handleMsg (line 43) | func (s *Server4) handleMsg(conn net.PacketConn, peer net.Addr,
    method Start (line 109) | func (s *Server4) Start() (err error) {

FILE: dhcps/dhcp6.go
  type Server6 (line 16) | type Server6 struct
    method handler (line 33) | func (s *Server6) handler(conn net.PacketConn, peer net.Addr,
    method handleMsg (line 47) | func (s *Server6) handleMsg(conn net.PacketConn, peer net.Addr,
    method process (line 168) | func (s *Server6) process(msg *dhcpv6.Message,
    method Start (line 252) | func (s *Server6) Start() (err error) {

FILE: dhcps/ndp.go
  type ServerNdp (line 15) | type ServerNdp struct
    method Start (line 32) | func (s *ServerNdp) Start() (err error) {
    method run (line 95) | func (s *ServerNdp) run() (err error) {
    method sendAdvertise (line 121) | func (s *ServerNdp) sendAdvertise(conn *ndp.Conn, dst netip.Addr) (err...
    method readSolicitations (line 188) | func (s *ServerNdp) readSolicitations(conn *ndp.Conn) (err error) {

FILE: dhcps/systemd.go
  constant dhcpCaps (line 27) | dhcpCaps = "CAP_NET_BIND_SERVICE CAP_NET_BROADCAST"
  constant ndpCaps (line 28) | ndpCaps  = "CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW"
  constant systemdTemplate (line 31) | systemdTemplate = `[Unit]
  constant systemdNamespaceTemplate (line 49) | systemdNamespaceTemplate = `[Unit]
  function UpdateEbtables (line 68) | func UpdateEbtables(vmId bson.ObjectID, namespace string) (err error) {
  function ClearEbtables (line 191) | func ClearEbtables(vmId bson.ObjectID, namespace string) (err error) {
  function WriteService (line 290) | func WriteService(vmId bson.ObjectID, namespace string,
  function Start (line 368) | func Start(db *database.Database, virt *vm.VirtualMachine,
  function Stop (line 483) | func Stop(virt *vm.VirtualMachine) (err error) {

FILE: disk/constants.go
  constant Provision (line 9) | Provision = "provision"
  constant Available (line 10) | Available = "available"
  constant Attached (line 11) | Attached  = "attached"
  constant Snapshot (line 13) | Snapshot = "snapshot"
  constant Backup (line 14) | Backup   = "backup"
  constant Expand (line 15) | Expand   = "expand"
  constant Restore (line 16) | Restore  = "restore"
  constant Destroy (line 17) | Destroy  = "destroy"
  constant Qcow2 (line 19) | Qcow2 = "qcow2"
  constant Lvm (line 20) | Lvm   = "lvm"
  constant Xfs (line 22) | Xfs     = "xfs"
  constant Ext4 (line 23) | Ext4    = "ext4"
  constant LvmXfs (line 24) | LvmXfs  = "lvm_xfs"
  constant LvmExt4 (line 25) | LvmExt4 = "lvm_ext4"
  constant Linux (line 27) | Linux         = "linux"
  constant LinuxLegacy (line 28) | LinuxLegacy   = "linux_legacy"
  constant LinuxUnsigned (line 29) | LinuxUnsigned = "linux_unsigned"
  constant Bsd (line 30) | Bsd           = "bsd"
  constant AlpineLinux (line 32) | AlpineLinux = "alpinelinux"
  constant ArchLinux (line 33) | ArchLinux   = "archlinux"
  constant RedHat (line 34) | RedHat      = "redhat"
  constant Fedora (line 35) | Fedora      = "fedora"
  constant Ubuntu (line 36) | Ubuntu      = "ubuntu"
  constant FreeBSD (line 37) | FreeBSD     = "freebsd"

FILE: disk/disk.go
  type Disk (line 23) | type Disk struct
    method IsActive (line 58) | func (d *Disk) IsActive() bool {
    method IsAvailable (line 62) | func (d *Disk) IsAvailable() bool {
    method Validate (line 69) | func (d *Disk) Validate(db *database.Database) (
    method PreCommit (line 293) | func (d *Disk) PreCommit() {
    method Reserve (line 298) | func (d *Disk) Reserve(db *database.Database,
    method Unreserve (line 326) | func (d *Disk) Unreserve(db *database.Database,
    method Commit (line 350) | func (d *Disk) Commit(db *database.Database) (err error) {
    method CommitFields (line 361) | func (d *Disk) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 374) | func (d *Disk) Insert(db *database.Database) (err error) {
    method Destroy (line 388) | func (d *Disk) Destroy(db *database.Database) (err error) {

FILE: disk/sort.go
  type Disks (line 3) | type Disks
    method Len (line 5) | func (d Disks) Len() int {
    method Swap (line 9) | func (d Disks) Swap(i, j int) {
    method Less (line 13) | func (d Disks) Less(i, j int) bool {

FILE: disk/utils.go
  function Get (line 13) | func Get(db *database.Database, diskId bson.ObjectID) (
  function GetOne (line 27) | func GetOne(db *database.Database, query *bson.M) (dsk *Disk, err error) {
  function GetOrg (line 40) | func GetOrg(db *database.Database, orgId, diskId bson.ObjectID) (
  function GetAll (line 58) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllMap (line 91) | func GetAllMap(db *database.Database, query *bson.M) (
  function GetAllPaged (line 124) | func GetAllPaged(db *database.Database, query *bson.M,
  function GetInstance (line 188) | func GetInstance(db *database.Database, instId bson.ObjectID) (
  function GetInstanceIndex (line 228) | func GetInstanceIndex(db *database.Database, instId bson.ObjectID,
  function GetNode (line 246) | func GetNode(db *database.Database, nodeId bson.ObjectID,
  function Remove (line 286) | func Remove(db *database.Database, diskId bson.ObjectID) (err error) {
  function Detach (line 305) | func Detach(db *database.Database, dskIds bson.ObjectID) (err error) {
  function Delete (line 323) | func Delete(db *database.Database, dskId bson.ObjectID) (err error) {
  function DeleteOrg (line 339) | func DeleteOrg(db *database.Database, orgId, dskId bson.ObjectID) (
  function DeleteMulti (line 360) | func DeleteMulti(db *database.Database, dskIds []bson.ObjectID) (
  function DeleteMultiOrg (line 385) | func DeleteMultiOrg(db *database.Database, orgId bson.ObjectID,
  function UpdateMulti (line 411) | func UpdateMulti(db *database.Database, dskIds []bson.ObjectID,
  function UpdateMultiOrg (line 439) | func UpdateMultiOrg(db *database.Database, orgId bson.ObjectID,
  function GetAllKeys (line 473) | func GetAllKeys(db *database.Database, ndeId bson.ObjectID) (
  function SetDeleteProtection (line 515) | func SetDeleteProtection(db *database.Database, instId bson.ObjectID,

FILE: dns/aws.go
  type Aws (line 18) | type Aws struct
    method Connect (line 24) | func (a *Aws) Connect(db *database.Database,
    method DnsZoneFind (line 53) | func (a *Aws) DnsZoneFind(domain string) (zoneId string, err error) {
    method DnsCommit (line 90) | func (a *Aws) DnsCommit(db *database.Database,
    method DnsFind (line 223) | func (a *Aws) DnsFind(db *database.Database, domain, recordType string) (
    method DnsTxtGet (line 273) | func (a *Aws) DnsTxtGet(db *database.Database, domain string) (
    method DnsTxtUpsert (line 312) | func (a *Aws) DnsTxtUpsert(db *database.Database,
    method DnsTxtDelete (line 353) | func (a *Aws) DnsTxtDelete(db *database.Database,

FILE: dns/cloudflare.go
  type Cloudflare (line 14) | type Cloudflare struct
    method Connect (line 20) | func (c *Cloudflare) Connect(db *database.Database,
    method DnsZoneFind (line 43) | func (c *Cloudflare) DnsZoneFind(db *database.Database, domain string) (
    method DnsCommit (line 80) | func (c *Cloudflare) DnsCommit(db *database.Database,
    method DnsFind (line 276) | func (c *Cloudflare) DnsFind(db *database.Database,
    method DnsTxtGet (line 323) | func (c *Cloudflare) DnsTxtGet(db *database.Database,
    method DnsTxtUpsert (line 362) | func (c *Cloudflare) DnsTxtUpsert(db *database.Database,
    method DnsTxtDelete (line 440) | func (c *Cloudflare) DnsTxtDelete(db *database.Database,

FILE: dns/constants.go
  constant UPSERT (line 4) | UPSERT = "upsert"
  constant DELETE (line 5) | DELETE = "delete"
  constant RETAIN (line 6) | RETAIN = "retain"

FILE: dns/dns.go
  type Operation (line 8) | type Operation struct
  type Service (line 13) | type Service interface

FILE: dns/errors.go
  type NotFoundError (line 7) | type NotFoundError struct
  type ServiceError (line 11) | type ServiceError struct
  type UnknownError (line 15) | type UnknownError struct

FILE: dns/google.go
  type Google (line 20) | type Google struct
    method Connect (line 45) | func (g *Google) Connect(db *database.Database,
    method DnsZoneFind (line 96) | func (g *Google) DnsZoneFind(db *database.Database, domain string) (
    method DnsCommit (line 158) | func (g *Google) DnsCommit(db *database.Database,
    method DnsFind (line 283) | func (g *Google) DnsFind(db *database.Database, domain, recordType str...
  type googleKey (line 26) | type googleKey struct
  type googleZoneInfo (line 39) | type googleZoneInfo struct

FILE: dns/oracle.go
  type Oracle (line 15) | type Oracle struct
    method OracleUser (line 21) | func (o *Oracle) OracleUser() string {
    method OraclePrivateKey (line 25) | func (o *Oracle) OraclePrivateKey() string {
    method Connect (line 29) | func (o *Oracle) Connect(db *database.Database,
    method DnsZoneFind (line 49) | func (o *Oracle) DnsZoneFind(db *database.Database, domain string) (
    method DnsCommit (line 100) | func (o *Oracle) DnsCommit(db *database.Database,
    method DnsFind (line 227) | func (o *Oracle) DnsFind(db *database.Database,
    method DnsTxtGet (line 271) | func (o *Oracle) DnsTxtGet(db *database.Database,
    method DnsTxtUpsert (line 306) | func (o *Oracle) DnsTxtUpsert(db *database.Database,
    method DnsTxtDelete (line 344) | func (o *Oracle) DnsTxtDelete(db *database.Database,

FILE: dns/utils.go
  function matchDomains (line 10) | func matchDomains(x, y string) bool {
  function matchTxt (line 17) | func matchTxt(x, y string) bool {
  function normalizeIp (line 24) | func normalizeIp(addr string) string {
  function extractDomain (line 33) | func extractDomain(domain string) string {
  function cleanDomain (line 42) | func cleanDomain(domain string) string {

FILE: dnss/constants.go
  constant Ttl (line 4) | Ttl = 10

FILE: dnss/database.go
  type Database (line 15) | type Database struct
  function init (line 21) | func init() {
  function UpdateDatabase (line 29) | func UpdateDatabase(db *Database) {
  function LoadConfig (line 33) | func LoadConfig(domains []*types.Domain) {

FILE: dnss/dnss.go
  type Server (line 15) | type Server struct
    method ListenUdp (line 21) | func (s *Server) ListenUdp() (err error) {
    method ListenTcp (line 33) | func (s *Server) ListenTcp() (err error) {
    method Shutdown (line 45) | func (s *Server) Shutdown() (err error) {
  function NewServer (line 59) | func NewServer(host string) (server *Server) {

FILE: dnss/plugin.go
  type Plugin (line 10) | type Plugin struct
    method ServeDNS (line 14) | func (p *Plugin) ServeDNS(ctx context.Context,
    method Name (line 183) | func (p *Plugin) Name() string {

FILE: dnss/response.go
  type Response (line 7) | type Response struct
    method WriteMsg (line 12) | func (r *Response) WriteMsg(m *dns.Msg) error {

FILE: domain/constants.go
  constant Local (line 6) | Local       = "local"
  constant AWS (line 7) | AWS         = "aws"
  constant Cloudflare (line 8) | Cloudflare  = "cloudflare"
  constant OracleCloud (line 9) | OracleCloud = "oracle_cloud"
  constant A (line 11) | A     = "A"
  constant AAAA (line 12) | AAAA  = "AAAA"
  constant CNAME (line 13) | CNAME = "CNAME"
  constant TXT (line 14) | TXT   = "TXT"
  constant INSERT (line 16) | INSERT = "insert"
  constant UPDATE (line 17) | UPDATE = "update"
  constant DELETE (line 18) | DELETE = "delete"

FILE: domain/domain.go
  type Domain (line 22) | type Domain struct
    method Locked (line 43) | func (d *Domain) Locked() bool {
    method Copy (line 48) | func (d *Domain) Copy() *Domain {
    method Json (line 66) | func (d *Domain) Json() {
    method Validate (line 80) | func (d *Domain) Validate(db *database.Database) (
    method PreCommit (line 146) | func (d *Domain) PreCommit() {
    method CommitRecords (line 150) | func (d *Domain) CommitRecords(db *database.Database) (err error) {
    method CommitRecordsSilent (line 159) | func (d *Domain) CommitRecordsSilent(db *database.Database) (err error) {
    method commitRecords (line 168) | func (d *Domain) commitRecords(db *database.Database,
    method syncBatches (line 288) | func (d *Domain) syncBatches(db *database.Database, secr *secret.Secret,
    method asyncBatches (line 306) | func (d *Domain) asyncBatches(db *database.Database, secr *secret.Secret,
    method UpdateRecords (line 349) | func (d *Domain) UpdateRecords(db *database.Database, secr *secret.Sec...
    method MergeRecords (line 443) | func (d *Domain) MergeRecords(deployId bson.ObjectID,
    method Commit (line 507) | func (d *Domain) Commit(db *database.Database) (err error) {
    method CommitFields (line 518) | func (d *Domain) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 531) | func (d *Domain) Insert(db *database.Database) (err error) {
    method GetDnsService (line 550) | func (d *Domain) GetDnsService(db *database.Database) (
    method preloadRecords (line 573) | func (d *Domain) preloadRecords(recs []*Record) {
    method LoadRecords (line 581) | func (d *Domain) LoadRecords(db *database.Database,
  type Completion (line 37) | type Completion struct

FILE: domain/record.go
  type Record (line 19) | type Record struct
    method Priority (line 32) | func (r *Record) Priority() int {
    method IsDeleted (line 45) | func (r *Record) IsDeleted() bool {
    method Copy (line 49) | func (r *Record) Copy() *Record {
    method Validate (line 54) | func (r *Record) Validate(db *database.Database) (
    method Commit (line 126) | func (r *Record) Commit(db *database.Database) (err error) {
    method CommitFields (line 137) | func (r *Record) CommitFields(db *database.Database, fields set.Set) (
    method Remove (line 150) | func (r *Record) Remove(db *database.Database) (err error) {
    method Insert (line 185) | func (r *Record) Insert(db *database.Database) (err error) {

FILE: domain/sort.go
  type Records (line 7) | type Records
    method Len (line 9) | func (r Records) Len() int {
    method Swap (line 13) | func (r Records) Swap(i, j int) {
    method Less (line 17) | func (r Records) Less(i, j int) bool {

FILE: domain/utils.go
  function Refresh (line 13) | func Refresh(db *database.Database, domnId bson.ObjectID) {
  function Get (line 72) | func Get(db *database.Database, domnId bson.ObjectID) (
  function GetOrg (line 86) | func GetOrg(db *database.Database, orgId, domnId bson.ObjectID) (
  function GetOne (line 104) | func GetOne(db *database.Database, query *bson.M) (domn *Domain, err err...
  function ExistsOrg (line 117) | func ExistsOrg(db *database.Database, orgId, domnId bson.ObjectID) (
  function GetAll (line 138) | func GetAll(db *database.Database, query *bson.M) (
  function GetLoadedAllIds (line 171) | func GetLoadedAllIds(db *database.Database, domnIds []bson.ObjectID) (
  function PreloadedRecords (line 237) | func PreloadedRecords(domns []*Domain, recs []*Record) []*Domain {
  function GetAllName (line 250) | func GetAllName(db *database.Database, query *bson.M) (
  function GetRecordAll (line 291) | func GetRecordAll(db *database.Database, query *bson.M) (
  function Lock (line 324) | func Lock(db *database.Database, domnId bson.ObjectID) (
  function Relock (line 363) | func Relock(db *database.Database, domnId,
  function Unlock (line 388) | func Unlock(db *database.Database, domnId,
  function Remove (line 416) | func Remove(db *database.Database, domnId bson.ObjectID) (err error) {
  function RemoveOrg (line 435) | func RemoveOrg(db *database.Database, orgId, domnId bson.ObjectID) (
  function RemoveMulti (line 457) | func RemoveMulti(db *database.Database, domnIds []bson.ObjectID) (err er...
  function RemoveMultiOrg (line 473) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: drive/drive.go
  type Device (line 14) | type Device struct

FILE: drive/utils.go
  function GetDevices (line 13) | func GetDevices() (devices []*Device, err error) {
  function GetDriveHashId (line 45) | func GetDriveHashId(id string) string {

FILE: engine/bash.go
  constant shellEnvExport (line 17) | shellEnvExport = `
  type BashEngine (line 25) | type BashEngine struct
    method Init (line 35) | func (b *BashEngine) Init(strt *Engine) (err error) {
    method streamOut (line 55) | func (b *BashEngine) streamOut(reader io.Reader) (env []string) {
    method streamErr (line 81) | func (b *BashEngine) streamErr(reader io.Reader) {
    method Run (line 107) | func (b *BashEngine) Run(block string) (err error) {

FILE: engine/constants.go
  constant QueueSize (line 4) | QueueSize = 256

FILE: engine/engine.go
  type Engine (line 16) | type Engine struct
    method UpdateEnv (line 29) | func (e *Engine) UpdateEnv(key, val string) {
    method UpdateCwd (line 33) | func (e *Engine) UpdateCwd(cwd string) {
    method ProcessOutput (line 37) | func (e *Engine) ProcessOutput(output string) {
    method GetEnv (line 43) | func (e *Engine) GetEnv() map[string]string {
    method GetCwd (line 47) | func (e *Engine) GetCwd() string {
    method GetEnviron (line 51) | func (e *Engine) GetEnviron() (env []string) {
    method Init (line 68) | func (e *Engine) Init() (err error) {
    method StartRunner (line 103) | func (e *Engine) StartRunner() {
    method getBlocks (line 107) | func (e *Engine) getBlocks() (blocks []*Block) {
    method UpdateSpec (line 120) | func (e *Engine) UpdateSpec(data string) (err error) {
    method runner (line 131) | func (e *Engine) runner() {
    method Run (line 153) | func (e *Engine) Run(phase string, blocks []*Block) (fatal bool, err e...
    method runBlock (line 202) | func (e *Engine) runBlock(blockType, block string) (err error) {
    method Queue (line 219) | func (e *Engine) Queue(data string) {

FILE: engine/parser.go
  type Block (line 8) | type Block struct
  constant Initial (line 16) | Initial = "initial"
  constant Reboot (line 17) | Reboot  = "reboot"
  constant Reload (line 18) | Reload  = "reload"
  constant Image (line 19) | Image   = "image"
  function Parse (line 26) | func Parse(data string) (blocks []*Block, err error) {
  function parseCodeBlockHeader (line 75) | func parseCodeBlockHeader(input string) (language string,

FILE: engine/python.go
  constant pyEngine (line 20) | pyEngine = `#!/usr/bin/env python3
  type pythonData (line 68) | type pythonData struct
  type PythonEngine (line 74) | type PythonEngine struct
    method Init (line 89) | func (p *PythonEngine) Init(strt *Engine) (err error) {
    method start (line 95) | func (p *PythonEngine) start() (err error) {
    method flushOutput (line 144) | func (p *PythonEngine) flushOutput() {
    method copyOutput (line 154) | func (p *PythonEngine) copyOutput(src io.ReadCloser) {
    method wait (line 220) | func (p *PythonEngine) wait() {
    method updateEnv (line 243) | func (p *PythonEngine) updateEnv() (err error) {
    method updateCwd (line 275) | func (p *PythonEngine) updateCwd() (err error) {
    method run (line 307) | func (p *PythonEngine) run(code string) (err error) {
    method Exit (line 339) | func (p *PythonEngine) Exit() (err error) {
    method Run (line 375) | func (p *PythonEngine) Run(code string) (err error) {

FILE: errortypes/errortypes.go
  type UnknownError (line 7) | type UnknownError struct
  type NotFoundError (line 11) | type NotFoundError struct
  type ReadError (line 15) | type ReadError struct
  type WriteError (line 19) | type WriteError struct
  type ParseError (line 23) | type ParseError struct
  type AuthenticationError (line 27) | type AuthenticationError struct
  type VerificationError (line 31) | type VerificationError struct
  type ApiError (line 35) | type ApiError struct
  type DatabaseError (line 39) | type DatabaseError struct
  type RequestError (line 43) | type RequestError struct
  type ConnectionError (line 47) | type ConnectionError struct
  type TimeoutError (line 51) | type TimeoutError struct
  type ExecError (line 55) | type ExecError struct
  type NetworkError (line 59) | type NetworkError struct
  type TypeError (line 63) | type TypeError struct
  type ErrorData (line 67) | type ErrorData struct
    method GetError (line 72) | func (e *ErrorData) GetError() (err error) {
  function GetErrorMessage (line 79) | func GetErrorMessage(err error) string {

FILE: eval/constants.go
  type Equal (line 7) | type Equal struct
  type NotEqual (line 8) | type NotEqual struct
  type Less (line 9) | type Less struct
  type LessEqual (line 10) | type LessEqual struct
  type Greater (line 11) | type Greater struct
  type GreaterEqual (line 12) | type GreaterEqual struct
  type If (line 13) | type If struct
  type And (line 14) | type And struct
  type Or (line 15) | type Or struct
  type For (line 16) | type For struct
  type Then (line 17) | type Then struct
  constant StatementMaxLength (line 20) | StatementMaxLength = 1024
  constant StatementMaxParts (line 21) | StatementMaxParts  = 30

FILE: eval/errortypes.go
  type EvalError (line 12) | type EvalError struct
  function NewEvalError (line 20) | func NewEvalError(statement string, index, errorIndex int,

FILE: eval/eval.go
  type Data (line 9) | type Data
  type Parser (line 11) | type Parser struct
    method parseRef (line 18) | func (p *Parser) parseRef(ref string, pos int) (val interface{}, err e...
    method parseComp (line 150) | func (p *Parser) parseComp(left, right, comp interface{}) bool {
    method Eval (line 231) | func (p *Parser) Eval() (resp string, threshold int, err error) {
  function Eval (line 535) | func Eval(data Data, statement string) (resp string,

FILE: eval/utils.go
  function Validate (line 8) | func Validate(statement string) (err error) {

FILE: event/event.go
  type Event (line 21) | type Event struct
  type EventPublish (line 28) | type EventPublish struct
  type CustomEvent (line 35) | type CustomEvent interface
  type Dispatch (line 40) | type Dispatch struct
  function getCursorId (line 44) | func getCursorId(db *database.Database, coll *database.Collection,
  function getCursorIdRetry (line 97) | func getCursorIdRetry(channels []string) bson.ObjectID {
  function Publish (line 124) | func Publish(db *database.Database, channel string, data interface{}) (
  function PublishDispatch (line 145) | func PublishDispatch(db *database.Database, typ string) (
  function Subscribe (line 160) | func Subscribe(channels []string, duration time.Duration,
  function SubscribeType (line 306) | func SubscribeType(channels []string, duration time.Duration,
  function Register (line 449) | func Register(channel string, callback func(*EventPublish)) {
  function subscribe (line 459) | func subscribe(channels []string) {
  function init (line 474) | func init() {

FILE: event/listener.go
  type Listener (line 17) | type Listener struct
    method Listen (line 25) | func (l *Listener) Listen() chan *Event {
    method Close (line 29) | func (l *Listener) Close() {
    method sub (line 36) | func (l *Listener) sub(cursorId bson.ObjectID) {
    method init (line 188) | func (l *Listener) init() (err error) {
  function SubscribeListener (line 210) | func SubscribeListener(db *database.Database, channels []string) (

FILE: event/socket.go
  type WebSocket (line 26) | type WebSocket struct
    method Close (line 34) | func (w *WebSocket) Close() {
  function WebSocketsStop (line 62) | func WebSocketsStop() {

FILE: features/qemu.go
  constant Libexec (line 24) | Libexec = "/usr/libexec/qemu-kvm"
  constant System (line 25) | System  = "/usr/bin/qemu-system-x86_64"
  type version (line 28) | type version struct
  function GetQemuPath (line 34) | func GetQemuPath() (path string, err error) {
  function GetQemuVersion (line 48) | func GetQemuVersion() (major, minor, patch int, err error) {
  function GetKernelVersion (line 121) | func GetKernelVersion() (major, minor, patch int, err error) {
  function GetUringSupport (line 195) | func GetUringSupport() (supported bool, err error) {
  function GetExtUringSupport (line 264) | func GetExtUringSupport() (supported bool, err error) {
  function GetMemoryBackendSupport (line 281) | func GetMemoryBackendSupport() (supported bool, err error) {
  function GetRunWithSupport (line 294) | func GetRunWithSupport() (supported bool, err error) {

FILE: features/systemd.go
  function GetSystemdVersion (line 10) | func GetSystemdVersion() (ver int) {
  function HasSystemdNamespace (line 39) | func HasSystemdNamespace() bool {

FILE: finder/constants.go
  constant DomainKind (line 4) | DomainKind      = "domain"
  constant VpcKind (line 5) | VpcKind         = "vpc"
  constant SubnetKind (line 6) | SubnetKind      = "subnet"
  constant DatacenterKind (line 7) | DatacenterKind  = "datacenter"
  constant NodeKind (line 8) | NodeKind        = "node"
  constant PoolKind (line 9) | PoolKind        = "pool"
  constant ZoneKind (line 10) | ZoneKind        = "zone"
  constant ShapeKind (line 11) | ShapeKind       = "shape"
  constant DiskKind (line 12) | DiskKind        = "disk"
  constant ImageKind (line 13) | ImageKind       = "image"
  constant BuildKind (line 14) | BuildKind       = "build"
  constant InstanceKind (line 15) | InstanceKind    = "instance"
  constant FirewallKind (line 16) | FirewallKind    = "firewall"
  constant PlanKind (line 17) | PlanKind        = "plan"
  constant CertificateKind (line 18) | CertificateKind = "certificate"
  constant SecretKind (line 19) | SecretKind      = "secret"
  constant PodKind (line 20) | PodKind         = "pod"
  constant UnitKind (line 21) | UnitKind        = "unit"
  constant JournalKind (line 22) | JournalKind     = "journal"

FILE: finder/resources.go
  type Resources (line 27) | type Resources struct
    method Find (line 52) | func (r *Resources) Find(db *database.Database, token string) (
  type PodBase (line 393) | type PodBase struct
  type UnitBase (line 399) | type UnitBase struct
  function GetPodBase (line 406) | func GetPodBase(db *database.Database, query *bson.M) (
  function GetUnitBase (line 421) | func GetUnitBase(db *database.Database, orgId bson.ObjectID,

FILE: firewall/constants.go
  constant All (line 6) | All       = "all"
  constant Icmp (line 7) | Icmp      = "icmp"
  constant Tcp (line 8) | Tcp       = "tcp"
  constant Udp (line 9) | Udp       = "udp"
  constant Multicast (line 10) | Multicast = "multicast"
  constant Broadcast (line 11) | Broadcast = "broadcast"

FILE: firewall/firewall.go
  type Rule (line 17) | type Rule struct
    method SetName (line 31) | func (r *Rule) SetName(ipv6 bool) (name string) {
  type Mapping (line 23) | type Mapping struct
  type Firewall (line 83) | type Firewall struct
    method Validate (line 92) | func (f *Firewall) Validate(db *database.Database) (
    method Commit (line 203) | func (f *Firewall) Commit(db *database.Database) (err error) {
    method CommitFields (line 214) | func (f *Firewall) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 227) | func (f *Firewall) Insert(db *database.Database) (err error) {

FILE: firewall/spec.go
  function GetSpecRules (line 18) | func GetSpecRules(instances []*instance.Instance,
  function GetSpecRulesSlow (line 156) | func GetSpecRulesSlow(db *database.Database,

FILE: firewall/utils.go
  function Get (line 21) | func Get(db *database.Database, fireId bson.ObjectID) (
  function GetOrg (line 35) | func GetOrg(db *database.Database, orgId, fireId bson.ObjectID) (
  function GetAll (line 53) | func GetAll(db *database.Database, query *bson.M) (
  function GetRoles (line 86) | func GetRoles(db *database.Database, roles []string) (
  function GetMapRoles (line 127) | func GetMapRoles(db *database.Database, roles []string) (
  function GetOrgMapRoles (line 170) | func GetOrgMapRoles(db *database.Database, orgId bson.ObjectID) (
  function GetOrgRoles (line 211) | func GetOrgRoles(db *database.Database, orgId bson.ObjectID,
  function GetAllPaged (line 252) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 318) | func Remove(db *database.Database, fireId bson.ObjectID) (err error) {
  function RemoveOrg (line 337) | func RemoveOrg(db *database.Database, orgId, fireId bson.ObjectID) (
  function RemoveMulti (line 359) | func RemoveMulti(db *database.Database, fireIds []bson.ObjectID) (
  function RemoveMultiOrg (line 377) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,
  function MergeIngress (line 396) | func MergeIngress(fires []*Firewall) (rules []*Rule) {
  function GetAllIngress (line 438) | func GetAllIngress(db *database.Database, nodeSelf *node.Node,
  function GetAllIngressPreloaded (line 539) | func GetAllIngressPreloaded(nodeSelf *node.Node,

FILE: geo/geo.go
  type Geo (line 22) | type Geo struct
  type geoData (line 37) | type geoData struct
  function get (line 42) | func get(addr string) (ge *Geo, err error) {
  function Get (line 100) | func Get(db *database.Database, addr string) (ge *Geo, err error) {

FILE: guest/guest.go
  type Command (line 13) | type Command struct
  type Response (line 18) | type Response struct

FILE: guest/power.go
  function Shutdown (line 15) | func Shutdown(vmId bson.ObjectID) (err error) {

FILE: hnetwork/hnetwork.go
  type IptablesRule (line 22) | type IptablesRule struct
    method Add (line 27) | func (h *IptablesRule) Add() (err error) {
    method Remove (line 64) | func (h *IptablesRule) Remove() (err error) {
  function loadIptablesNat (line 98) | func loadIptablesNat() (rules []*IptablesRule, err error) {
  function removeNetwork (line 167) | func removeNetwork(stat *state.State) (err error) {
  function ApplyState (line 182) | func ApplyState(stat *state.State) (err error) {

FILE: hnetwork/utils.go
  function create (line 12) | func create() (err error) {
  function getAddr (line 32) | func getAddr() (addr string, err error) {
  function setAddr (line 46) | func setAddr(addr string) (err error) {
  function clearAddr (line 77) | func clearAddr() (err error) {

FILE: hugepages/hugepages.go
  function HugepageSize (line 14) | func HugepageSize() (count int, size uint64, err error) {
  function UpdateHugepagesSize (line 36) | func UpdateHugepagesSize() (err error) {

FILE: image/constants.go
  constant Uefi (line 9) | Uefi    = "uefi"
  constant Bios (line 10) | Bios    = "bios"
  constant Unknown (line 11) | Unknown = "unknown"
  constant Linux (line 13) | Linux         = "linux"
  constant LinuxLegacy (line 14) | LinuxLegacy   = "linux_legacy"
  constant LinuxUnsigned (line 15) | LinuxUnsigned = "linux_unsigned"
  constant Bsd (line 16) | Bsd           = "bsd"
  constant RedHat (line 18) | RedHat = "redhat"
  constant Fedora (line 19) | Fedora = "fedora"
  constant Ubuntu (line 20) | Ubuntu = "ubuntu"
  constant AlmaLinux8 (line 22) | AlmaLinux8    = "almalinux8"
  constant AlmaLinux9 (line 23) | AlmaLinux9    = "almalinux9"
  constant AlmaLinux10 (line 24) | AlmaLinux10   = "almalinux10"
  constant AlmaLinux11 (line 25) | AlmaLinux11   = "almalinux11"
  constant AlmaLinux12 (line 26) | AlmaLinux12   = "almalinux12"
  constant AlmaLinux13 (line 27) | AlmaLinux13   = "almalinux13"
  constant AlmaLinux14 (line 28) | AlmaLinux14   = "almalinux14"
  constant AlmaLinux15 (line 29) | AlmaLinux15   = "almalinux15"
  constant AlmaLinux16 (line 30) | AlmaLinux16   = "almalinux16"
  constant AlpineLinux (line 31) | AlpineLinux   = "alpinelinux"
  constant ArchLinux (line 32) | ArchLinux     = "archlinux"
  constant Fedora42 (line 33) | Fedora42      = "fedora42"
  constant Fedora43 (line 34) | Fedora43      = "fedora43"
  constant Fedora44 (line 35) | Fedora44      = "fedora44"
  constant Fedora45 (line 36) | Fedora45      = "fedora45"
  constant Fedora46 (line 37) | Fedora46      = "fedora46"
  constant Fedora47 (line 38) | Fedora47      = "fedora47"
  constant Fedora48 (line 39) | Fedora48      = "fedora48"
  constant Fedora49 (line 40) | Fedora49      = "fedora49"
  constant Fedora50 (line 41) | Fedora50      = "fedora50"
  constant Fedora51 (line 42) | Fedora51      = "fedora51"
  constant Fedora52 (line 43) | Fedora52      = "fedora52"
  constant Fedora53 (line 44) | Fedora53      = "fedora53"
  constant Fedora54 (line 45) | Fedora54      = "fedora54"
  constant Fedora55 (line 46) | Fedora55      = "fedora55"
  constant Fedora56 (line 47) | Fedora56      = "fedora56"
  constant Fedora57 (line 48) | Fedora57      = "fedora57"
  constant Fedora58 (line 49) | Fedora58      = "fedora58"
  constant Fedora59 (line 50) | Fedora59      = "fedora59"
  constant Fedora60 (line 51) | Fedora60      = "fedora60"
  constant Fedora61 (line 52) | Fedora61      = "fedora61"
  constant Fedora62 (line 53) | Fedora62      = "fedora62"
  constant FreeBSD (line 54) | FreeBSD       = "freebsd"
  constant OracleLinux7 (line 55) | OracleLinux7  = "oraclelinux7"
  constant OracleLinux8 (line 56) | OracleLinux8  = "oraclelinux8"
  constant OracleLinux9 (line 57) | OracleLinux9  = "oraclelinux9"
  constant OracleLinux10 (line 58) | OracleLinux10 = "oraclelinux10"
  constant OracleLinux11 (line 59) | OracleLinux11 = "oraclelinux11"
  constant OracleLinux12 (line 60) | OracleLinux12 = "oraclelinux12"
  constant OracleLinux13 (line 61) | OracleLinux13 = "oraclelinux13"
  constant OracleLinux14 (line 62) | OracleLinux14 = "oraclelinux14"
  constant OracleLinux15 (line 63) | OracleLinux15 = "oraclelinux15"
  constant OracleLinux16 (line 64) | OracleLinux16 = "oraclelinux16"
  constant RockyLinux8 (line 65) | RockyLinux8   = "rockylinux8"
  constant RockyLinux9 (line 66) | RockyLinux9   = "rockylinux9"
  constant RockyLinux10 (line 67) | RockyLinux10  = "rockylinux10"
  constant RockyLinux11 (line 68) | RockyLinux11  = "rockylinux11"
  constant RockyLinux12 (line 69) | RockyLinux12  = "rockylinux12"
  constant RockyLinux13 (line 70) | RockyLinux13  = "rockylinux13"
  constant RockyLinux14 (line 71) | RockyLinux14  = "rockylinux14"
  constant RockyLinux15 (line 72) | RockyLinux15  = "rockylinux15"
  constant RockyLinux16 (line 73) | RockyLinux16  = "rockylinux16"
  constant Ubuntu2404 (line 74) | Ubuntu2404    = "ubuntu2404"
  constant Ubuntu2604 (line 75) | Ubuntu2604    = "ubuntu2604"
  constant Ubuntu2804 (line 76) | Ubuntu2804    = "ubuntu2804"
  constant Ubuntu3004 (line 77) | Ubuntu3004    = "ubuntu3004"
  constant Ubuntu3204 (line 78) | Ubuntu3204    = "ubuntu3204"
  constant Ubuntu3404 (line 79) | Ubuntu3404    = "ubuntu3404"
  constant Ubuntu3604 (line 80) | Ubuntu3604    = "ubuntu3604"
  constant Ubuntu3804 (line 81) | Ubuntu3804    = "ubuntu3804"
  constant Ubuntu4004 (line 82) | Ubuntu4004    = "ubuntu4004"
  constant Ubuntu4204 (line 83) | Ubuntu4204    = "ubuntu4204"
  constant Ubuntu4404 (line 84) | Ubuntu4404    = "ubuntu4404"

FILE: image/errortypes.go
  type LostImageError (line 7) | type LostImageError struct

FILE: image/image.go
  type Image (line 17) | type Image struct
    method Validate (line 54) | func (i *Image) Validate(db *database.Database) (
    method Parse (line 85) | func (i *Image) Parse() {
    method GetSystemType (line 95) | func (i *Image) GetSystemType() string {
    method GetSystemKind (line 124) | func (i *Image) GetSystemKind() string {
    method Json (line 161) | func (i *Image) Json() {
    method Commit (line 165) | func (i *Image) Commit(db *database.Database) (err error) {
    method CommitFields (line 176) | func (i *Image) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 189) | func (i *Image) Insert(db *database.Database) (err error) {
    method Upsert (line 201) | func (i *Image) Upsert(db *database.Database) (err error) {
    method Sync (line 245) | func (i *Image) Sync(db *database.Database) (err error) {
    method Remove (line 340) | func (i *Image) Remove(db *database.Database) (err error) {
  type Completion (line 40) | type Completion struct

FILE: image/sort.go
  type ImagesSort (line 7) | type ImagesSort
    method Len (line 9) | func (x ImagesSort) Len() int {
    method Swap (line 13) | func (x ImagesSort) Swap(i, j int) {
    method Less (line 17) | func (x ImagesSort) Less(i, j int) bool {
  type CompletionsSort (line 21) | type CompletionsSort
    method Len (line 23) | func (x CompletionsSort) Len() int {
    method Swap (line 27) | func (x CompletionsSort) Swap(i, j int) {
    method Less (line 31) | func (x CompletionsSort) Less(i, j int) bool {

FILE: image/utils.go
  function GetEtag (line 25) | func GetEtag(info minio.ObjectInfo) string {
  function ParseImageName (line 36) | func ParseImageName(key string) (name, release, build string) {
  function Get (line 81) | func Get(db *database.Database, imgId bson.ObjectID) (
  function GetKey (line 95) | func GetKey(db *database.Database, storeId bson.ObjectID, key string) (
  function GetOrg (line 113) | func GetOrg(db *database.Database, orgId, imgId bson.ObjectID) (
  function GetOrgPublic (line 131) | func GetOrgPublic(db *database.Database, orgId, imgId bson.ObjectID) (
  function GetOne (line 149) | func GetOne(db *database.Database, query *bson.M) (img *Image, err error) {
  function Distinct (line 162) | func Distinct(db *database.Database, storeId bson.ObjectID) (
  function ExistsOrg (line 179) | func ExistsOrg(db *database.Database, orgId, imgId bson.ObjectID) (
  function GetAll (line 200) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllCompletion (line 233) | func GetAllCompletion(db *database.Database, query *bson.M) (
  function GetAllPaged (line 283) | func GetAllPaged(db *database.Database, query *bson.M, page, pageCount i...
  function GetAllNames (line 344) | func GetAllNames(db *database.Database, query *bson.M) (
  function GetAllKeys (line 390) | func GetAllKeys(db *database.Database) (keys set.Set, err error) {
  function Remove (line 430) | func Remove(db *database.Database, imgId bson.ObjectID) (err error) {

FILE: imds/config.go
  function BuildConfig (line 25) | func BuildConfig(inst *instance.Instance, virt *vm.VirtualMachine,
  function SetConfigs (line 54) | func SetConfigs(cnfs map[bson.ObjectID]*types.Config) {
  function GetConfigs (line 60) | func GetConfigs() (

FILE: imds/imds.go
  constant counterMax (line 41) | counterMax = 2000000000
  function mergeUpdateDetails (line 44) | func mergeUpdateDetails(db *database.Database, instId bson.ObjectID,
  function Sync (line 83) | func Sync(db *database.Database, namespace string,
  function Pull (line 479) | func Pull(db *database.Database, instId, deplyId bson.ObjectID,
  function State (line 671) | func State(db *database.Database, instId bson.ObjectID,

FILE: imds/resource/resource.go
  function Query (line 11) | func Query(resrc string, keys ...string) (val string, err error) {

FILE: imds/resource/utils.go
  function selector (line 15) | func selector(v interface{}, key string, isJson bool) (val string, err e...
  function jsonValString (line 90) | func jsonValString(value any) string {
  function selectString (line 110) | func selectString(obj interface{}) string {

FILE: imds/server/constants/constants.go
  constant Version (line 8) | Version     = "1.0.3229.20"
  constant ConfRefresh (line 9) | ConfRefresh = 500 * time.Millisecond

FILE: imds/server/errortypes/errortypes.go
  type UnknownError (line 7) | type UnknownError struct
  type NotFoundError (line 11) | type NotFoundError struct
  type ReadError (line 15) | type ReadError struct
  type WriteError (line 19) | type WriteError struct
  type ParseError (line 23) | type ParseError struct
  type AuthenticationError (line 27) | type AuthenticationError struct
  type VerificationError (line 31) | type VerificationError struct
  type ApiError (line 35) | type ApiError struct
  type DatabaseError (line 39) | type DatabaseError struct
  type RequestError (line 43) | type RequestError struct
  type ConnectionError (line 47) | type ConnectionError struct
  type TimeoutError (line 51) | type TimeoutError struct
  type ExecError (line 55) | type ExecError struct
  type NetworkError (line 59) | type NetworkError struct
  type TypeError (line 63) | type TypeError struct
  type ErrorData (line 67) | type ErrorData struct

FILE: imds/server/handlers/certificate.go
  function certificatesGet (line 8) | func certificatesGet(c *gin.Context) {

FILE: imds/server/handlers/dhcp.go
  function dhcpPut (line 12) | func dhcpPut(c *gin.Context) {

FILE: imds/server/handlers/handlers.go
  type AuthenticationError (line 14) | type AuthenticationError struct
  function Recovery (line 19) | func Recovery(c *gin.Context) {
  function Errors (line 35) | func Errors(c *gin.Context) {
  function AuthVirt (line 44) | func AuthVirt(c *gin.Context) {
  function AuthDhcp (line 75) | func AuthDhcp(c *gin.Context) {
  function AuthHost (line 94) | func AuthHost(c *gin.Context) {
  function RegisterVirt (line 113) | func RegisterVirt(engine *gin.Engine) {
  function RegisterHost (line 139) | func RegisterHost(engine *gin.Engine) {

FILE: imds/server/handlers/instance.go
  function instanceGet (line 8) | func instanceGet(c *gin.Context) {

FILE: imds/server/handlers/node.go
  function nodeGet (line 8) | func nodeGet(c *gin.Context) {

FILE: imds/server/handlers/query.go
  function queryGet (line 8) | func queryGet(c *gin.Context) {

FILE: imds/server/handlers/secret.go
  function secretsGet (line 8) | func secretsGet(c *gin.Context) {

FILE: imds/server/handlers/sync.go
  type syncRespData (line 23) | type syncRespData struct
  function syncPut (line 29) | func syncPut(c *gin.Context) {
  function hostSyncPut (line 83) | func hostSyncPut(c *gin.Context) {
  function hostSyncGet (line 115) | func hostSyncGet(c *gin.Context) {
  function hostStateGet (line 130) | func hostStateGet(c *gin.Context) {

FILE: imds/server/handlers/vpc.go
  function vpcGet (line 8) | func vpcGet(c *gin.Context) {
  function subnetGet (line 12) | func subnetGet(c *gin.Context) {

FILE: imds/server/router/router.go
  type Router (line 21) | type Router struct
    method Run (line 27) | func (r *Router) Run() (err error) {
    method Shutdown (line 121) | func (r *Router) Shutdown() {
    method Init (line 141) | func (r *Router) Init() {

FILE: imds/server/server.go
  function Main (line 15) | func Main() (err error) {

FILE: imds/server/state/state.go
  type Store (line 15) | type Store struct
    method AppendOutput (line 22) | func (s *Store) AppendOutput(entry *types.Entry) {
    method GetOutput (line 29) | func (s *Store) GetOutput() (entries []*types.Entry) {
    method AppendJournalOutput (line 40) | func (s *Store) AppendJournalOutput(key string, entry *types.Entry) {
    method GetJournals (line 55) | func (s *Store) GetJournals() (journals map[string][]*types.Entry) {
  function Init (line 91) | func Init() (err error) {

FILE: imds/server/utils/files.go
  function Chmod (line 16) | func Chmod(pth string, mode os.FileMode) (err error) {
  function Exists (line 28) | func Exists(pth string) (exists bool, err error) {
  function ExistsDir (line 46) | func ExistsDir(pth string) (exists bool, err error) {
  function ExistsFile (line 64) | func ExistsFile(pth string) (exists bool, err error) {
  function ExistsMkdir (line 82) | func ExistsMkdir(pth string, perm os.FileMode) (err error) {
  function ExistsRemove (line 101) | func ExistsRemove(pth string) (err error) {
  function Remove (line 120) | func Remove(path string) (err error) {
  function RemoveAll (line 139) | func RemoveAll(path string) (err error) {
  function ContainsDir (line 158) | func ContainsDir(pth string) (hasDir bool, err error) {
  function Open (line 182) | func Open(path string, perm os.FileMode) (file *os.File, err error) {
  function Read (line 194) | func Read(path string) (data string, err error) {
  function ReadLines (line 207) | func ReadLines(path string) (lines []string, err error) {
  function Write (line 238) | func Write(path string, data string, perm os.FileMode) (err error) {
  function Create (line 264) | func Create(path string, perm os.FileMode) (file *os.File, err error) {
  function CreateWrite (line 276) | func CreateWrite(path string, data string, perm os.FileMode) (err error) {

FILE: imds/server/utils/misc.go
  function StringsContains (line 3) | func StringsContains(val []string, str string) bool {

FILE: imds/server/utils/request.go
  function StripPort (line 7) | func StripPort(hostport string) string {

FILE: imds/systemd.go
  constant systemdNamespaceTemplate (line 20) | systemdNamespaceTemplate = `[Unit]
  constant systemdTemplate (line 43) | systemdTemplate = `[Unit]
  function WriteService (line 65) | func WriteService(vmId bson.ObjectID,
  function Start (line 113) | func Start(db *database.Database, virt *vm.VirtualMachine) (err error) {
  function Restart (line 145) | func Restart(instId bson.ObjectID) (err error) {
  function Stop (line 153) | func Stop(virt *vm.VirtualMachine) (err error) {

FILE: imds/types/certificate.go
  type Certificate (line 8) | type Certificate struct
  function NewCertificates (line 16) | func NewCertificates(certs []*certificate.Certificate) []*Certificate {

FILE: imds/types/config.go
  type Config (line 9) | type Config struct
    method ComputeHash (line 26) | func (c *Config) ComputeHash() (err error) {

FILE: imds/types/constants.go
  constant Initializing (line 4) | Initializing   = "initializing"
  constant ReloadingClean (line 5) | ReloadingClean = "reloading_clean"
  constant ReloadingFault (line 6) | ReloadingFault = "reloading_fault"
  constant Running (line 7) | Running        = "running"
  constant Fault (line 8) | Fault          = "fault"
  constant Offline (line 9) | Offline        = "offline"
  constant Imaged (line 10) | Imaged         = "imaged"

FILE: imds/types/domain.go
  type Domain (line 7) | type Domain struct

FILE: imds/types/instance.go
  type Instance (line 10) | type Instance struct
  function NewInstance (line 59) | func NewInstance(inst *instance.Instance) *Instance {

FILE: imds/types/journal.go
  type Journal (line 7) | type Journal struct
  function NewJournals (line 15) | func NewJournals(spc *spec.Spec) []*Journal {

FILE: imds/types/node.go
  type Node (line 8) | type Node struct
  function NewNode (line 15) | func NewNode(nde *node.Node) *Node {

FILE: imds/types/pod.go
  type Pod (line 10) | type Pod struct
  type Unit (line 16) | type Unit struct
  function NewPods (line 44) | func NewPods(pods []*pod.Pod, podUnitsMap map[bson.ObjectID][]*unit.Unit,

FILE: imds/types/secret.go
  type Secret (line 8) | type Secret struct
  function NewSecrets (line 20) | func NewSecrets(secrs []*secret.Secret) []*Secret {

FILE: imds/types/state.go
  type State (line 10) | type State struct
    method Final (line 29) | func (s *State) Final() bool {
    method Copy (line 36) | func (s *State) Copy() *State {
  type Entry (line 55) | type Entry struct
  constant Error (line 62) | Error = 3
  constant Info (line 63) | Info  = 5

FILE: imds/types/vpc.go
  type Vpc (line 10) | type Vpc struct
  type Subnet (line 20) | type Subnet struct
    method String (line 26) | func (s *Subnet) String() string {
  type Route (line 30) | type Route struct
    method String (line 35) | func (r *Route) String() string {
  function NewSubnet (line 39) | func NewSubnet(subnet *vpc.Subnet) *Subnet {
  function NewRoute (line 50) | func NewRoute(subnet *vpc.Route) *Route {
  function NewVpc (line 60) | func NewVpc(vpc *vpc.Vpc) *Vpc {

FILE: info/instance.go
  function NewInstance (line 16) | func NewInstance(stat *state.State, inst *instance.Instance) (

FILE: instance/constants.go
  constant Starting (line 8) | Starting     = "starting"
  constant Running (line 9) | Running      = "running"
  constant Stopped (line 10) | Stopped      = "stopped"
  constant Failed (line 11) | Failed       = "failed"
  constant Updating (line 12) | Updating     = "updating"
  constant Provisioning (line 13) | Provisioning = "provisioning"
  constant Bridge (line 14) | Bridge       = "bridge"
  constant Vxlan (line 15) | Vxlan        = "vxlan"
  constant Start (line 17) | Start       = "start"
  constant Stop (line 18) | Stop        = "stop"
  constant Cleanup (line 19) | Cleanup     = "cleanup"
  constant Restart (line 20) | Restart     = "restart"
  constant Destroy (line 21) | Destroy     = "destroy"
  constant Linux (line 22) | Linux       = "linux"
  constant LinuxLegacy (line 23) | LinuxLegacy = "linux_legacy"
  constant BSD (line 24) | BSD         = "bsd"
  constant AlpineLinux (line 26) | AlpineLinux = "alpinelinux"
  constant ArchLinux (line 27) | ArchLinux   = "archlinux"
  constant RedHat (line 28) | RedHat      = "redhat"
  constant Fedora (line 29) | Fedora      = "fedora"
  constant Ubuntu (line 30) | Ubuntu      = "ubuntu"
  constant FreeBSD (line 31) | FreeBSD     = "freebsd"
  constant HostPath (line 33) | HostPath = "host_path"

FILE: instance/errortypes.go
  type VncDialError (line 7) | type VncDialError struct

FILE: instance/instance.go
  type Instance (line 42) | type Instance struct
    method GenerateId (line 186) | func (i *Instance) GenerateId() (err error) {
    method Validate (line 200) | func (i *Instance) Validate(db *database.Database) (
    method GenerateUnixId (line 634) | func (i *Instance) GenerateUnixId() {
    method InitUnixId (line 638) | func (i *Instance) InitUnixId(db *database.Database) (err error) {
    method GenerateSpicePort (line 653) | func (i *Instance) GenerateSpicePort() {
    method InitSpicePort (line 658) | func (i *Instance) InitSpicePort(db *database.Database) (err error) {
    method GenerateVncDisplay (line 690) | func (i *Instance) GenerateVncDisplay() {
    method InitVncDisplay (line 696) | func (i *Instance) InitVncDisplay(db *database.Database) (err error) {
    method Format (line 728) | func (i *Instance) Format() {
    method Json (line 731) | func (i *Instance) Json(short bool) {
    method IsActive (line 852) | func (i *Instance) IsActive() bool {
    method IsIpv6Only (line 857) | func (i *Instance) IsIpv6Only() bool {
    method PreCommit (line 863) | func (i *Instance) PreCommit() {
    method UpsertNodePorts (line 878) | func (i *Instance) UpsertNodePorts(newNodePorts []*nodeport.Mapping) {
    method SyncNodePorts (line 929) | func (i *Instance) SyncNodePorts(db *database.Database) (err error) {
    method PostCommit (line 1008) | func (i *Instance) PostCommit(db *database.Database) (
    method Cleanup (line 1061) | func (i *Instance) Cleanup(db *database.Database) (err error) {
    method Commit (line 1099) | func (i *Instance) Commit(db *database.Database) (err error) {
    method CommitFields (line 1110) | func (i *Instance) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 1145) | func (i *Instance) Insert(db *database.Database) (err error) {
    method LoadVirt (line 1179) | func (i *Instance) LoadVirt(poolsMap map[bson.ObjectID]*pool.Pool,
    method Changed (line 1348) | func (i *Instance) Changed(curVirt *vm.VirtualMachine) (bool, string) {
    method DiskChanged (line 1513) | func (i *Instance) DiskChanged(curVirt *vm.VirtualMachine) (
    method UsbChanged (line 1552) | func (i *Instance) UsbChanged(curVirt *vm.VirtualMachine) (
    method VncConnect (line 1607) | func (i *Instance) VncConnect(db *database.Database,
  type Completion (line 136) | type Completion struct
  type Mount (line 146) | type Mount struct
  type StatusInfo (line 153) | type StatusInfo struct
  type GuestData (line 158) | type GuestData struct
  type Info (line 170) | type Info struct

FILE: instance/utils.go
  function Get (line 17) | func Get(db *database.Database, instId bson.ObjectID) (
  function GetOrg (line 31) | func GetOrg(db *database.Database, orgId, instId bson.ObjectID) (
  function GetOne (line 49) | func GetOne(db *database.Database, query *bson.M) (inst *Instance, err e...
  function ExistsIp (line 62) | func ExistsIp(db *database.Database, addr string) (exists bool, err erro...
  function ExistsOrg (line 88) | func ExistsOrg(db *database.Database, orgId, instId bson.ObjectID) (
  function GetAll (line 109) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllRoles (line 142) | func GetAllRoles(db *database.Database, query *bson.M) (
  function GetAllVirt (line 180) | func GetAllVirt(db *database.Database, query *bson.M,
  function GetAllVirtMapped (line 245) | func GetAllVirtMapped(db *database.Database, query *bson.M,
  function LoadAllVirt (line 308) | func LoadAllVirt(insts []*Instance, pools []*pool.Pool,
  function GetAllName (line 344) | func GetAllName(db *database.Database, query *bson.M) (
  function GetAllPaged (line 380) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 446) | func Remove(db *database.Database, instId bson.ObjectID) (err error) {
  function Delete (line 494) | func Delete(db *database.Database, instId bson.ObjectID) (err error) {
  function DeleteOrg (line 510) | func DeleteOrg(db *database.Database, orgId, instId bson.ObjectID) (
  function DeleteMulti (line 529) | func DeleteMulti(db *database.Database, instIds []bson.ObjectID) (
  function DeleteMultiOrg (line 554) | func DeleteMultiOrg(db *database.Database, orgId bson.ObjectID,
  function UpdateMulti (line 580) | func UpdateMulti(db *database.Database, instIds []bson.ObjectID,
  function UpdateMultiOrg (line 611) | func UpdateMultiOrg(db *database.Database, orgId bson.ObjectID,
  function SetAction (line 643) | func SetAction(db *database.Database, instId bson.ObjectID,
  function SetDownloadProgress (line 666) | func SetDownloadProgress(db *database.Database,

FILE: interfaces/interfaces.go
  function getIfaces (line 21) | func getIfaces(bridge string) (ifacesSet set.Set, err error) {
  function SyncIfaces (line 36) | func SyncIfaces(vxlan bool) {
  function GetExternal (line 109) | func GetExternal(virtIface string) (externalIface string) {
  function HasExternal (line 149) | func HasExternal() (exists bool) {
  function GetInternal (line 164) | func GetInternal(virtIface string, vxlan bool) (internalIface string) {
  function GetBridges (line 208) | func GetBridges(nde *node.Node) (bridges set.Set) {
  function GetBridgesInternal (line 240) | func GetBridgesInternal(nde *node.Node) (bridges set.Set) {
  function GetBridgesExternal (line 251) | func GetBridgesExternal(nde *node.Node) (bridges set.Set) {
  function RemoveVirtIface (line 278) | func RemoveVirtIface(virtIface string) {

FILE: ip/interface.go
  type Interface (line 3) | type Interface struct

FILE: ip/ip.go
  type Iface (line 20) | type Iface struct
    method GetAddress (line 50) | func (iface *Iface) GetAddress() string {
    method GetAddress6 (line 77) | func (iface *Iface) GetAddress6() string {
  function GetIfaces (line 104) | func GetIfaces(namespace string) (ifaces []*Iface, err error) {
  function GetIfacesCached (line 136) | func GetIfacesCached(namespace string) (ifacesMap map[string]*Iface, err...
  function ClearIfacesCache (line 163) | func ClearIfacesCache(namespace string) {

FILE: iproute/address.go
  type Address (line 12) | type Address struct
  type AddressIface (line 22) | type AddressIface struct
  function AddressGetIface (line 28) | func AddressGetIface(namespace, name string) (
  function AddressGetIfaceMod (line 126) | func AddressGetIfaceMod(namespace, name string) (

FILE: iproute/bridge.go
  function BridgeAdd (line 7) | func BridgeAdd(namespace, name string) (err error) {
  function BridgeDelete (line 39) | func BridgeDelete(namespace, name string) (err error) {

FILE: iproute/iface.go
  type Iface (line 11) | type Iface struct
  function IfaceGetAll (line 16) | func IfaceGetAll(namespace string) (ifaces []*Iface, err error) {
  function IfaceGetBridges (line 49) | func IfaceGetBridges(namespace string) (ifaces []*Iface, err error) {
  function IfaceGetBridgeIfaces (line 84) | func IfaceGetBridgeIfaces(namespace, bridge string) (

FILE: ipset/names.go
  type Names (line 8) | type Names struct
    method Apply (line 13) | func (n *Names) Apply(curNames *Names) (err error) {

FILE: ipset/sets.go
  type Sets (line 10) | type Sets struct
    method Apply (line 15) | func (s *Sets) Apply(curSets *Sets) (err error) {

FILE: ipset/state.go
  type State (line 10) | type State struct
    method AddIngress (line 14) | func (s *State) AddIngress(namespace string, ingress []*firewall.Rule) {
    method AddSourceDestCheck (line 60) | func (s *State) AddSourceDestCheck(namespace, addr6 string) {
    method AddMember (line 78) | func (s *State) AddMember(namespace string, ruleName, member string) {
  type NamesState (line 101) | type NamesState struct
    method AddIngress (line 105) | func (n *NamesState) AddIngress(namespace string, ingress []*firewall....
    method AddSourceDestCheck (line 141) | func (n *NamesState) AddSourceDestCheck(namespace string) {
    method AddName (line 154) | func (n *NamesState) AddName(namespace string, ruleName string) {

FILE: ipset/utils.go
  function UpdateState (line 21) | func UpdateState(instances []*instance.Instance, namespaces []string,
  function applyState (line 75) | func applyState(oldState, newState *State, namespaces []string) (err err...
  function UpdateNamesState (line 106) | func UpdateNamesState(instances []*instance.Instance,
  function applyNamesState (line 155) | func applyNamesState(oldNamesState, newNamesState *NamesState) (err erro...
  function loadIpset (line 168) | func loadIpset(namespace string, state *State, namesState *NamesState) (
  function Init (line 207) | func Init(namespaces []string, instances []*instance.Instance,
  function InitNames (line 241) | func InitNames(namespaces []string, instances []*instance.Instance,

FILE: iptables/iptables.go
  method newCommand (line 24) | func (r *Rules) newCommand() (cmd []string) {
  method newCommandNatPre (line 39) | func (r *Rules) newCommandNatPre() (cmd []string) {
  method newCommandNatPost (line 47) | func (r *Rules) newCommandNatPost() (cmd []string) {
  method newCommandMap (line 55) | func (r *Rules) newCommandMap() (cmd []string) {
  method newCommandMapPost (line 63) | func (r *Rules) newCommandMapPost() (cmd []string) {
  method commentCommand (line 71) | func (r *Rules) commentCommand(inCmd []string, hold bool) (cmd []string) {
  method commentCommandHeader (line 87) | func (r *Rules) commentCommandHeader(inCmd []string) (cmd []string) {
  method commentCommandSdc (line 96) | func (r *Rules) commentCommandSdc(inCmd []string) (cmd []string) {
  method commentCommandNat (line 105) | func (r *Rules) commentCommandNat(inCmd []string) (cmd []string) {
  method commentCommandMap (line 114) | func (r *Rules) commentCommandMap(inCmd []string) (cmd []string) {
  method run (line 123) | func (r *Rules) run(table string, cmds [][]string,
  method Apply (line 189) | func (r *Rules) Apply(diff *RulesDiff) (err error) {
  method Hold (line 279) | func (r *Rules) Hold() (err error) {
  method Remove (line 377) | func (r *Rules) Remove(diff *RulesDiff) (err error) {
  function generateVirt (line 473) | func generateVirt(vc *vpc.Vpc, namespace, iface, addr, addr6 string,
  function generateInternal (line 966) | func generateInternal(namespace, iface string, nat, nat6, dhcp, dhcp6 bool,
  function generateNodePort (line 1390) | func generateNodePort(namespace, iface string, addr, nodePortGateway str...
  function generateHost (line 1507) | func generateHost(namespace, iface string, nodePortNetwork bool,
  function generateHostNodePort (line 1967) | func generateHostNodePort(namespace, iface string,

FILE: iptables/lock.go
  function Lock (line 9) | func Lock() {
  function Unlock (line 13) | func Unlock() {

FILE: iptables/rules.go
  type Rules (line 7) | type Rules struct
  type RulesDiff (line 25) | type RulesDiff struct

FILE: iptables/state.go
  type State (line 14) | type State struct
  function LoadState (line 18) | func LoadState(nodeSelf *node.Node, vpcs []*vpc.Vpc,

FILE: iptables/update.go
  type Update (line 18) | type Update struct
    method Apply (line 25) | func (u *Update) Apply() {
    method Recover (line 167) | func (u *Update) Recover() {
    method reload (line 193) | func (u *Update) reload() (err error) {
  function ApplyUpdate (line 243) | func ApplyUpdate(newState *State, namespaces []string, recover bool) {
  function UpdateState (line 266) | func UpdateState(nodeSelf *node.Node, vpcs []*vpc.Vpc,
  function UpdateStateRecover (line 279) | func UpdateStateRecover(nodeSelf *node.Node, vpcs []*vpc.Vpc,

FILE: iptables/utils.go
  function diffCmd (line 18) | func diffCmd(a, b []string) bool {
  function diffRules (line 32) | func diffRules(a, b *Rules) *RulesDiff {
  function getIptablesCmd (line 199) | func getIptablesCmd(ipv6 bool) string {
  function loadIptables (line 207) | func loadIptables(namespace, instIface string, state *State,
  function RecoverNode (line 664) | func RecoverNode() (err error) {
  function Init (line 726) | func Init(namespaces []string, vpcs []*vpc.Vpc,
  function protocolIndex (line 829) | func protocolIndex(proto string) string {

FILE: ipvs/constants.go
  constant Tcp (line 4) | Tcp = "-t"
  constant Udp (line 5) | Udp = "-u"
  constant RoundRobin (line 7) | RoundRobin = "rr"

FILE: ipvs/ipvs.go
  type State (line 18) | type State struct
    method Print (line 22) | func (s *State) Print() string {
    method AddTarget (line 72) | func (s *State) AddTarget(serviceAddr, targetAddr string,
  function UpdateState (line 99) | func UpdateState(newState *State) (err error) {
  function LoadState (line 261) | func LoadState() (state *State, err error) {
  function New (line 383) | func New() *State {

FILE: ipvs/service.go
  type Service (line 15) | type Service struct
    method Key (line 23) | func (s *Service) Key() string {
    method Add (line 27) | func (s *Service) Add() (err error) {
    method Delete (line 69) | func (s *Service) Delete() (err error) {

FILE: ipvs/target.go
  type Target (line 11) | type Target struct
    method Key (line 19) | func (t *Target) Key() string {
    method Add (line 23) | func (t *Target) Add() (err error) {
    method Delete (line 55) | func (t *Target) Delete() (err error) {

FILE: iscsi/iscsi.go
  type Device (line 12) | type Device struct
    method Json (line 22) | func (d *Device) Json() {
    method QemuUri (line 43) | func (d *Device) QemuUri() (uriStr string) {
    method Parse (line 72) | func (d *Device) Parse() (errData *errortypes.ErrorData, err error) {

FILE: iso/iso.go
  type Iso (line 20) | type Iso struct
  function GetIsos (line 24) | func GetIsos(isoDir string) (isos []*Iso, err error) {

FILE: journal/constants.go
  constant InstanceAgent (line 4) | InstanceAgent   = 1
  constant DeploymentAgent (line 5) | DeploymentAgent = 2
  constant Panic (line 9) | Panic    = 1
  constant Critical (line 10) | Critical = 2
  constant Error (line 11) | Error    = 3
  constant Warning (line 12) | Warning  = 4
  constant Info (line 13) | Info     = 5
  constant Debug (line 14) | Debug    = 6
  constant Trace (line 15) | Trace    = 7

FILE: journal/journal.go
  type Journal (line 11) | type Journal struct
    method String (line 22) | func (j *Journal) String() string {
    method Insert (line 30) | func (j *Journal) Insert(db *database.Database) (err error) {

FILE: journal/store.go
  type KindGenerator (line 7) | type KindGenerator interface

FILE: journal/utils.go
  function GetOutput (line 13) | func GetOutput(c context.Context, db *database.Database,
  function Remove (line 68) | func Remove(db *database.Database, resource bson.ObjectID,
  function RemoveAll (line 90) | func RemoveAll(db *database.Database, resource bson.ObjectID) (err error) {

FILE: lock/lvm.go
  type LvmLocker (line 12) | type LvmLocker struct
  function LvmLock (line 18) | func LvmLock(db *database.Database, vgName, lvName string) (
  function LvmRelock (line 44) | func LvmRelock(db *database.Database, vgName, lvName string) (err error) {
  function LvmUnlock (line 61) | func LvmUnlock(db *database.Database, vgName, lvName string) (err error) {

FILE: log/constants.go
  constant Debug (line 4) | Debug   = "debug"
  constant Info (line 5) | Info    = "info"
  constant Warning (line 6) | Warning = "warning"
  constant Error (line 7) | Error   = "error"
  constant Fatal (line 8) | Fatal   = "fatal"
  constant Panic (line 9) | Panic   = "panic"
  constant Unknown (line 10) | Unknown = "unknown"

FILE: log/log.go
  type Entry (line 16) | type Entry struct
    method Insert (line 25) | func (e *Entry) Insert(db *database.Database) (err error) {
  function publish (line 46) | func publish() {
  function initSender (line 53) | func initSender() {
  function init (line 63) | func init() {

FILE: log/utils.go
  function Get (line 11) | func Get(db *database.Database, logId bson.ObjectID) (
  function GetAll (line 25) | func GetAll(db *database.Database, query *bson.M, page, pageCount int64) (
  function Clear (line 89) | func Clear(db *database.Database) (err error) {

FILE: logger/database.go
  type databaseSender (line 17) | type databaseSender struct
    method Init (line 19) | func (s *databaseSender) Init() {}
    method Parse (line 21) | func (s *databaseSender) Parse(entry *logrus.Entry) {
  function databaseSend (line 27) | func databaseSend(entry *logrus.Entry) (err error) {
  function initDatabaseSender (line 82) | func initDatabaseSender() {
  function init (line 105) | func init() {

FILE: logger/file.go
  type fileSender (line 12) | type fileSender struct
    method Init (line 14) | func (s *fileSender) Init() {}
    method Parse (line 16) | func (s *fileSender) Parse(entry *logrus.Entry) {
    method send (line 25) | func (s *fileSender) send(entry *logrus.Entry) (err error) {
  function init (line 78) | func init() {

FILE: logger/formatter.go
  function format (line 19) | func format(entry *logrus.Entry) (output []byte) {
  function formatPlain (line 69) | func formatPlain(entry *logrus.Entry) (output []byte) {
  function formatTime (line 117) | func formatTime(timestamp time.Time) (str string) {
  function formatLevel (line 125) | func formatLevel(lvl logrus.Level) (str string) {
  function formatLevelPlain (line 153) | func formatLevelPlain(lvl logrus.Level) string {
  type formatter (line 171) | type formatter struct
    method Format (line 173) | func (f *formatter) Format(entry *logrus.Entry) ([]byte, error) {

FILE: logger/hook.go
  type logHook (line 9) | type logHook struct
    method Fire (line 11) | func (h *logHook) Fire(entry *logrus.Entry) (err error) {
    method Levels (line 23) | func (h *logHook) Levels() []logrus.Level {

FILE: logger/limiter.go
  type limiter (line 10) | type limiter
    method Check (line 12) | func (l limiter) Check(entry *logrus.Entry, limit time.Duration) bool {

FILE: logger/logger.go
  function initSender (line 17) | func initSender() {
  function Init (line 41) | func Init() {
  function InitStdout (line 48) | func InitStdout() {
  function init (line 54) | func init() {

FILE: logger/sender.go
  type sender (line 7) | type sender interface

FILE: logger/writer.go
  type ErrorWriter (line 9) | type ErrorWriter struct
    method Write (line 15) | func (w *ErrorWriter) Write(input []byte) (n int, err error) {

FILE: lvm/lv.go
  function CreateLv (line 15) | func CreateLv(vgName, lvName string, size int) (err error) {
  function RemoveLv (line 26) | func RemoveLv(vgName, lvName string) (err error) {
  function ActivateLv (line 37) | func ActivateLv(vgName, lvName string) (err error) {
  function DeactivateLv (line 47) | func DeactivateLv(vgName, lvName string) (err error) {
  function WriteLv (line 57) | func WriteLv(vgName, lvName, sourcePth string) (err error) {
  function ExtendLv (line 71) | func ExtendLv(vgName, lvName string, addSize int) (err error) {
  function GetSizeLv (line 82) | func GetSizeLv(vgName, lvName string) (size int, err error) {
  function HasLocking (line 105) | func HasLocking(vgName string) (hasLock bool, err error) {
  function IsLockspaceActive (line 118) | func IsLockspaceActive(vgName string) (isLocked bool, err error) {
  function InitLock (line 138) | func InitLock(vgName string) (err error) {

FILE: lvm/vgs.go
  type report (line 21) | type report struct
  type vgReport (line 25) | type vgReport struct
  type vgDetails (line 29) | type vgDetails struct
  function GetAvailablePools (line 39) | func GetAvailablePools(db *database.Database, zoneId bson.ObjectID) (

FILE: main.go
  constant help (line 16) | help = `
  function Init (line 38) | func Init() {
  function InitLimited (line 43) | func InitLimited() {
  function main (line 48) | func main() {

FILE: middlewear/gzip.go
  type GzipWriter (line 11) | type GzipWriter struct
    method Header (line 16) | func (g *GzipWriter) Header() http.Header {
    method WriteHeader (line 20) | func (g *GzipWriter) WriteHeader(statusCode int) {
    method Write (line 24) | func (g *GzipWriter) Write(b []byte) (int, error) {
    method Close (line 31) | func (g *GzipWriter) Close() {
  function NewGzipWriter (line 37) | func NewGzipWriter(c *gin.Context) *GzipWriter {

FILE: middlewear/middlewear.go
  constant robots (line 24) | robots = `User-agent: *
  function Limiter (line 28) | func Limiter(c *gin.Context) {
  function Counter (line 32) | func Counter(c *gin.Context) {
  function Database (line 36) | func Database(c *gin.Context) {
  function Headers (line 43) | func Headers(c *gin.Context) {
  function SessionAdmin (line 53) | func SessionAdmin(c *gin.Context) {
  function SessionUser (line 101) | func SessionUser(c *gin.Context) {
  function AuthAdmin (line 148) | func AuthAdmin(c *gin.Context) {
  function AuthUser (line 207) | func AuthUser(c *gin.Context) {
  function UserOrg (line 266) | func UserOrg(c *gin.Context) {
  function CsrfToken (line 313) | func CsrfToken(c *gin.Context) {
  function Recovery (line 351) | func Recovery(c *gin.Context) {
  function RobotsGet (line 374) | func RobotsGet(c *gin.Context) {
  function NotFound (line 378) | func NotFound(c *gin.Context) {

FILE: mtu/mtu.go
  type Check (line 21) | type Check struct
    method host (line 30) | func (c *Check) host(db *database.Database) (err error) {
    method instances (line 99) | func (c *Check) instances(db *database.Database) (err error) {
    method Run (line 161) | func (c *Check) Run() (err error) {
  function NewCheck (line 199) | func NewCheck() (chk *Check) {

FILE: netconf/address.go
  method Address (line 15) | func (n *NetConf) Address(db *database.Database) (err error) {

FILE: netconf/base.go
  method Base (line 8) | func (n *NetConf) Base(db *database.Database) (err error) {

FILE: netconf/bridge.go
  method bridgeNet (line 10) | func (n *NetConf) bridgeNet(db *database.Database) (err error) {
  method bridgeMaster (line 49) | func (n *NetConf) bridgeMaster(db *database.Database) (err error) {
  method bridgeRoute (line 73) | func (n *NetConf) bridgeRoute(db *database.Database) (err error) {
  method bridgeIptables (line 99) | func (n *NetConf) bridgeIptables(db *database.Database) (err error) {
  method bridgeUp (line 199) | func (n *NetConf) bridgeUp(db *database.Database) (err error) {
  method Bridge (line 223) | func (n *NetConf) Bridge(db *database.Database) (err error) {

FILE: netconf/clear.go
  method Clear (line 14) | func (n *NetConf) Clear(db *database.Database) (err error) {
  method ClearAll (line 39) | func (n *NetConf) ClearAll(db *database.Database) (err error) {
  function clearIface (line 59) | func clearIface(namespace, iface string) {

FILE: netconf/external.go
  method externalNet (line 15) | func (n *NetConf) externalNet(db *database.Database) (err error) {
  method externalMtu (line 59) | func (n *NetConf) externalMtu(db *database.Database) (err error) {
  method externalUp (line 98) | func (n *NetConf) externalUp(db *database.Database) (err error) {
  method externalSysctl (line 118) | func (n *NetConf) externalSysctl(db *database.Database) (err error) {
  method externalMaster (line 144) | func (n *NetConf) externalMaster(db *database.Database) (err error) {
  method externalSpace (line 165) | func (n *NetConf) externalSpace(db *database.Database) (err error) {
  method externalSpaceMod (line 195) | func (n *NetConf) externalSpaceMod(db *database.Database) (err error) {
  method externalSpaceSysctl (line 253) | func (n *NetConf) externalSpaceSysctl(db *database.Database) (err error) {
  method externalSpaceUp (line 357) | func (n *NetConf) externalSpaceUp(db *database.Database) (err error) {
  method External (line 401) | func (n *NetConf) External(db *database.Database) (err error) {

FILE: netconf/host.go
  method hostNet (line 11) | func (n *NetConf) hostNet(db *database.Database) (err error) {
  method hostMtu (line 38) | func (n *NetConf) hostMtu(db *database.Database) (err error) {
  method hostUp (line 65) | func (n *NetConf) hostUp(db *database.Database) (err error) {
  method hostMaster (line 80) | func (n *NetConf) hostMaster(db *database.Database) (err error) {
  method hostSpace (line 96) | func (n *NetConf) hostSpace(db *database.Database) (err error) {
  method hostSpaceUp (line 122) | func (n *NetConf) hostSpaceUp(db *database.Database) (err error) {
  method Host (line 138) | func (n *NetConf) Host(db *database.Database) (err error) {

FILE: netconf/iface.go
  method Iface1 (line 18) | func (n *NetConf) Iface1(db *database.Database) (err error) {
  method Iface2 (line 105) | func (n *NetConf) Iface2(db *database.Database, clean bool) (err error) {

FILE: netconf/imds.go
  method imdsNet (line 10) | func (n *NetConf) imdsNet(db *database.Database) (err error) {
  method imdsMtu (line 28) | func (n *NetConf) imdsMtu(db *database.Database) (err error) {
  method imdsAddr (line 43) | func (n *NetConf) imdsAddr(db *database.Database) (err error) {
  method imdsUp (line 58) | func (n *NetConf) imdsUp(db *database.Database) (err error) {
  method imdsStart (line 72) | func (n *NetConf) imdsStart(db *database.Database) (err error) {
  method Imds (line 81) | func (n *NetConf) Imds(db *database.Database) (err error) {

FILE: netconf/internal.go
  method internalNet (line 11) | func (n *NetConf) internalNet(db *database.Database) (err error) {
  method internalMtu (line 51) | func (n *NetConf) internalMtu(db *database.Database) (err error) {
  method internalUp (line 78) | func (n *NetConf) internalUp(db *database.Database) (err error) {
  method internalMaster (line 93) | func (n *NetConf) internalMaster(db *database.Database) (err error) {
  method internalSpace (line 109) | func (n *NetConf) internalSpace(db *database.Database) (err error) {
  method internalSpaceUp (line 135) | func (n *NetConf) internalSpaceUp(db *database.Database) (err error) {
  method Internal (line 149) | func (n *NetConf) Internal(db *database.Database) (err error) {

FILE: netconf/ip.go
  method ipExternal (line 23) | func (n *NetConf) ipExternal(db *database.Database) (err error) {
  method ipHost (line 250) | func (n *NetConf) ipHost(db *database.Database) (err error) {
  method ipNodePort (line 280) | func (n *NetConf) ipNodePort(db *database.Database) (err error) {
  method ipDetect (line 297) | func (n *NetConf) ipDetect(db *database.Database) (err error) {
  method ipHostIptables (line 378) | func (n *NetConf) ipHostIptables(db *database.Database) (err error) {
  method ipDatabase (line 456) | func (n *NetConf) ipDatabase(db *database.Database) (err error) {
  method ipInit6 (line 525) | func (n *NetConf) ipInit6(db *database.Database) (err error) {
  method ipArp (line 592) | func (n *NetConf) ipArp(db *database.Database) (err error) {
  method ipInit6Alt (line 660) | func (n *NetConf) ipInit6Alt(db *database.Database) (err error) {
  method Ip (line 702) | func (n *NetConf) Ip(db *database.Database) (err error) {

FILE: netconf/netconf.go
  type NetConf (line 17) | type NetConf struct
    method Init (line 112) | func (n *NetConf) Init(db *database.Database) (err error) {
    method Clean (line 196) | func (n *NetConf) Clean(db *database.Database) (err error) {

FILE: netconf/nodeport.go
  method nodePortNet (line 11) | func (n *NetConf) nodePortNet(db *database.Database) (err error) {
  method nodePortMtu (line 38) | func (n *NetConf) nodePortMtu(db *database.Database) (err error) {
  method nodePortUp (line 65) | func (n *NetConf) nodePortUp(db *database.Database) (err error) {
  method nodePortMaster (line 80) | func (n *NetConf) nodePortMaster(db *database.Database) (err error) {
  method nodePortSpace (line 96) | func (n *NetConf) nodePortSpace(db *database.Database) (err error) {
  method nodePortSpaceUp (line 122) | func (n *NetConf) nodePortSpaceUp(db *database.Database) (err error) {
  method NodePort (line 138) | func (n *NetConf) NodePort(db *database.Database) (err error) {

FILE: netconf/oracle.go
  method oracleInitVnic (line 19) | func (n *NetConf) oracleInitVnic(db *database.Database) (err error) {
  method oracleConfVnic (line 92) | func (n *NetConf) oracleConfVnic(db *database.Database) (err error) {
  method oracleConfVnicMetal (line 116) | func (n *NetConf) oracleConfVnicMetal(db *database.Database) (err error) {
  method oracleConfVnicVirt (line 266) | func (n *NetConf) oracleConfVnicVirt(db *database.Database) (err error) {
  method oracleMtu (line 386) | func (n *NetConf) oracleMtu(db *database.Database) (err error) {
  method oracleIp (line 414) | func (n *NetConf) oracleIp(db *database.Database) (err error) {
  method oracleUp (line 460) | func (n *NetConf) oracleUp(db *database.Database) (err error) {
  method oracleRoute (line 486) | func (n *NetConf) oracleRoute(db *database.Database) (err error) {
  method Oracle (line 516) | func (n *NetConf) Oracle(db *database.Database) (err error) {

FILE: netconf/space.go
  method spaceSysctl (line 12) | func (n *NetConf) spaceSysctl(db *database.Database) (err error) {
  method spaceForward (line 77) | func (n *NetConf) spaceForward(db *database.Database) (err error) {
  method spaceVirt (line 207) | func (n *NetConf) spaceVirt(db *database.Database) (err error) {
  method spaceLoopback (line 224) | func (n *NetConf) spaceLoopback(db *database.Database) (err error) {
  method spaceMtu (line 238) | func (n *NetConf) spaceMtu(db *database.Database) (err error) {
  method spaceUp (line 255) | func (n *NetConf) spaceUp(db *database.Database) (err error) {
  method Space (line 269) | func (n *NetConf) Space(db *database.Database) (err error) {

FILE: netconf/utils.go
  function New (line 10) | func New(virt *vm.VirtualMachine) *NetConf {
  function Destroy (line 16) | func Destroy(db *database.Database, virt *vm.VirtualMachine) (err error) {

FILE: netconf/validate.go
  method Validate (line 14) | func (n *NetConf) Validate() (err error) {

FILE: netconf/vlan.go
  method vlanNet (line 10) | func (n *NetConf) vlanNet(db *database.Database) (err error) {
  method vlanMtu (line 27) | func (n *NetConf) vlanMtu(db *database.Database) (err error) {
  method vlanUp (line 44) | func (n *NetConf) vlanUp(db *database.Database) (err error) {
  method Vlan (line 58) | func (n *NetConf) Vlan(db *database.Database) (err error) {

FILE: node/block.go
  type BlockAttachment (line 5) | type BlockAttachment struct

FILE: node/certificate.go
  function selfCert (line 20) | func selfCert(parent *x509.Certificate, parentKey *ecdsa.PrivateKey) (
  function SelfCert (line 86) | func SelfCert() (certPem, keyPem []byte, err error) {

FILE: node/constants.go
  constant Admin (line 8) | Admin      = "admin"
  constant User (line 9) | User       = "user"
  constant Balancer (line 10) | Balancer   = "balancer"
  constant Hypervisor (line 11) | Hypervisor = "hypervisor"
  constant Qemu (line 13) | Qemu = "qemu"
  constant Kvm (line 14) | Kvm  = "kvm"
  constant Std (line 17) | Std = "std"
  constant Vmware (line 19) | Vmware = "vmware"
  constant Virtio (line 21) | Virtio = "virtio"
  constant VirtioPci (line 23) | VirtioPci = "virtio_pci"
  constant VirtioVgaGl (line 25) | VirtioVgaGl = "virtio_vga_gl"
  constant VirtioVgaGlVulkan (line 27) | VirtioVgaGlVulkan = "virtio_vga_gl_vulkan"
  constant VirtioGl (line 29) | VirtioGl = "virtio_gl"
  constant VirtioGlVulkan (line 31) | VirtioGlVulkan = "virtio_gl_vulkan"
  constant VirtioPciGl (line 33) | VirtioPciGl = "virtio_pci_gl"
  constant VirtioPciGlVulkan (line 35) | VirtioPciGlVulkan = "virtio_pci_gl_vulkan"
  constant VirtioPrime (line 37) | VirtioPrime = "virtio_prime"
  constant VirtioPciPrime (line 39) | VirtioPciPrime = "virtio_pci_prime"
  constant VirtioVgaGlPrime (line 41) | VirtioVgaGlPrime = "virtio_vga_gl_prime"
  constant VirtioVgaGlVulkanPrime (line 43) | VirtioVgaGlVulkanPrime = "virtio_vga_gl_vulkan_prime"
  constant VirtioGlPrime (line 45) | VirtioGlPrime = "virtio_gl_prime"
  constant VirtioGlVulkanPrime (line 47) | VirtioGlVulkanPrime = "virtio_gl_vulkan_prime"
  constant VirtioPciGlPrime (line 49) | VirtioPciGlPrime = "virtio_pci_gl_prime"
  constant VirtioPciGlVulkanPrime (line 51) | VirtioPciGlVulkanPrime = "virtio_pci_gl_vulkan_prime"
  constant Sdl (line 53) | Sdl = "sdl"
  constant Gtk (line 54) | Gtk = "gtk"
  constant Disabled (line 56) | Disabled  = "disabled"
  constant Dhcp (line 57) | Dhcp      = "dhcp"
  constant DhcpSlaac (line 58) | DhcpSlaac = "dhcp_slaac"
  constant Slaac (line 59) | Slaac     = "slaac"
  constant Static (line 60) | Static    = "static"
  constant Internal (line 61) | Internal  = "internal"
  constant Cloud (line 62) | Cloud     = "cloud"
  constant Restart (line 64) | Restart = "restart"
  constant HostPath (line 66) | HostPath = "host_path"

FILE: node/interfaces.go
  function ClearIfaceCache (line 21) | func ClearIfaceCache() {
  function GetInterfaces (line 28) | func GetInterfaces() (ifaces []ip.Interface, err error) {
  function getDefaultIface (line 75) | func getDefaultIface() (iface string, err error) {

FILE: node/node.go
  type Node (line 49) | type Node struct
    method Copy (line 192) | func (n *Node) Copy() *Node {
    method AddRequest (line 289) | func (n *Node) AddRequest() {
    method GetVirtPath (line 296) | func (n *Node) GetVirtPath() string {
    method GetCachePath (line 303) | func (n *Node) GetCachePath() string {
    method GetTempPath (line 310) | func (n *Node) GetTempPath() string {
    method GetDatacenter (line 317) | func (n *Node) GetDatacenter(db *database.Database) (
    method GetCloudSubnetsName (line 342) | func (n *Node) GetCloudSubnetsName() (subnets []*CloudSubnet) {
    method IsAdmin (line 384) | func (n *Node) IsAdmin() bool {
    method IsUser (line 393) | func (n *Node) IsUser() bool {
    method IsBalancer (line 402) | func (n *Node) IsBalancer() bool {
    method IsHypervisor (line 411) | func (n *Node) IsHypervisor() bool {
    method IsOnline (line 420) | func (n *Node) IsOnline() bool {
    method IsDhcp (line 429) | func (n *Node) IsDhcp() bool {
    method IsDhcp6 (line 434) | func (n *Node) IsDhcp6() bool {
    method Usage (line 439) | func (n *Node) Usage() int {
    method SizeResource (line 458) | func (n *Node) SizeResource(memory, processors int) bool {
    method GetOracleAuthProvider (line 472) | func (n *Node) GetOracleAuthProvider() (pv *NodeOracleAuthProvider) {
    method GetWebauthn (line 479) | func (n *Node) GetWebauthn(origin string, strict bool) (
    method Validate (line 514) | func (n *Node) Validate(db *database.Database) (
    method Format (line 853) | func (n *Node) Format() {
    method JsonHypervisor (line 858) | func (n *Node) JsonHypervisor() {
    method SetActive (line 884) | func (n *Node) SetActive() {
    method Commit (line 898) | func (n *Node) Commit(db *database.Database) (err error) {
    method CommitFields (line 909) | func (n *Node) CommitFields(db *database.Database, fields set.Set) (
    method GetStaticAddr (line 922) | func (n *Node) GetStaticAddr(db *database.Database,
    method GetStaticAddr6 (line 977) | func (n *Node) GetStaticAddr6(db *database.Database,
    method GetStaticHostAddr (line 1049) | func (n *Node) GetStaticHostAddr(db *database.Database,
    method GetStaticNodePortAddr (line 1099) | func (n *Node) GetStaticNodePortAddr(db *database.Database,
    method GetRemoteAddr (line 1149) | func (n *Node) GetRemoteAddr(r *http.Request) (addr string) {
    method SyncNetwork (line 1162) | func (n *Node) SyncNetwork(clearCache bool) {
    method getUpdateDetails (line 1268) | func (n *Node) getUpdateDetails(db *database.Database) (
    method update (line 1296) | func (n *Node) update(db *database.Database) (err error) {
    method sync (line 1409) | func (n *Node) sync() (nde *Node) {
    method Init (line 1590) | func (n *Node) Init() (err error) {
  type Completion (line 141) | type Completion struct
    method IsHypervisor (line 148) | func (n *Completion) IsHypervisor() bool {
  type Share (line 157) | type Share struct
    method MatchPath (line 163) | func (s *Share) MatchPath(pth string) bool {
  type CloudSubnet (line 187) | type CloudSubnet struct

FILE: node/oracle.go
  type NodeOracleAuthProvider (line 3) | type NodeOracleAuthProvider struct
    method OracleUser (line 7) | func (n *NodeOracleAuthProvider) OracleUser() string {
    method OracleTenancy (line 11) | func (n *NodeOracleAuthProvider) OracleTenancy() string {
    method OraclePrivateKey (line 15) | func (n *NodeOracleAuthProvider) OraclePrivateKey() string {

FILE: node/utils.go
  function Get (line 10) | func Get(db *database.Database, nodeId bson.ObjectID) (
  function GetAll (line 24) | func GetAll(db *database.Database) (nodes []*Node, err error) {
  function GetOne (line 56) | func GetOne(db *database.Database, query *bson.M) (nde *Node, err error) {
  function GetAllNamesMap (line 69) | func GetAllNamesMap(db *database.Database, query *bson.M) (
  function GetAllHypervisors (line 108) | func GetAllHypervisors(db *database.Database, query *bson.M) (
  function GetAllPool (line 163) | func GetAllPool(db *database.Database, poolId bson.ObjectID) (
  function GetAllPaged (line 204) | func GetAllPaged(db *database.Database, query *bson.M,
  function GetAllShape (line 271) | func GetAllShape(db *database.Database, zones []bson.ObjectID,
  function GetAllNet (line 321) | func GetAllNet(db *database.Database) (nodes []*Node, err error) {
  function Remove (line 356) | func Remove(db *database.Database, nodeId bson.ObjectID) (err error) {

FILE: nodeport/constants.go
  constant Tcp (line 4) | Tcp = "tcp"
  constant Udp (line 5) | Udp = "udp"

FILE: nodeport/mapping.go
  type Mapping (line 9) | type Mapping struct
    method Validate (line 17) | func (m *Mapping) Validate(db *database.Database) (
    method Diff (line 66) | func (m *Mapping) Diff(mapping *Mapping) bool {

FILE: nodeport/network.go
  function init (line 16) | func init() {

FILE: nodeport/nodeport.go
  type NodePort (line 10) | type NodePort struct
    method Validate (line 18) | func (n *NodePort) Validate(db *database.Database) (
    method Sync (line 59) | func (n *NodePort) Sync(db *database.Database) (err error) {
    method CommitFields (line 80) | func (n *NodePort) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 93) | func (n *NodePort) Insert(db *database.Database) (err error) {

FILE: nodeport/utils.go
  type PortRange (line 16) | type PortRange struct
    method Contains (line 21) | func (r *PortRange) Contains(port int) bool {
  function Get (line 28) | func Get(db *database.Database, ndePrtId bson.ObjectID) (
  function GetOrg (line 45) | func GetOrg(db *database.Database, orgId, ndePrtId bson.ObjectID) (
  function GetPort (line 63) | func GetPort(db *database.Database, dcId, orgId bson.ObjectID,
  function Available (line 81) | func Available(db *database.Database, datacenterId, orgId bson.ObjectID,
  function GetPortRanges (line 102) | func GetPortRanges() (ranges []*PortRange, err error) {
  function New (line 159) | func New(db *database.Database, dcId, orgId bson.ObjectID,
  function Remove (line 226) | func Remove(db *database.Database, ndePrtId bson.ObjectID) (

FILE: nonce/nonce.go
  type nonce (line 11) | type nonce struct
  function Validate (line 16) | func Validate(db *database.Database, nce string) (err error) {

FILE: notification/notification.go
  type notificationResp (line 34) | type notificationResp struct
  function Check (line 39) | func Check() (err error) {

FILE: oracle/iface.go
  type Iface (line 11) | type Iface struct
  function GetIfaces (line 23) | func GetIfaces(logOutput bool) (ifaces []*Iface, err error) {
  function ConfIfaces (line 80) | func ConfIfaces(logOutput bool) (err error) {

FILE: oracle/metadata.go
  type Metadata (line 17) | type Metadata struct
  type OciMetaVnic (line 27) | type OciMetaVnic struct
  type OciMetaInstance (line 40) | type OciMetaInstance struct
  type OciMeta (line 48) | type OciMeta struct
    method IsBareMetal (line 53) | func (o *OciMeta) IsBareMetal() bool {
  function GetMetadata (line 60) | func GetMetadata(authPv AuthProvider) (mdata *Metadata, err error) {
  function GetOciMetadata (line 108) | func GetOciMetadata() (mdata *OciMeta, err error) {

FILE: oracle/oracle.go
  type AuthProvider (line 3) | type AuthProvider interface

FILE: oracle/provider.go
  type Provider (line 14) | type Provider struct
    method LogInfo (line 26) | func (p *Provider) LogInfo() {
    method AuthType (line 38) | func (p *Provider) AuthType() (common.AuthConfig, error) {
    method PrivateRSAKey (line 46) | func (p *Provider) PrivateRSAKey() (*rsa.PrivateKey, error) {
    method KeyID (line 50) | func (p *Provider) KeyID() (string, error) {
    method TenancyOCID (line 54) | func (p *Provider) TenancyOCID() (string, error) {
    method UserOCID (line 58) | func (p *Provider) UserOCID() (string, error) {
    method KeyFingerprint (line 62) | func (p *Provider) KeyFingerprint() (string, error) {
    method Region (line 66) | func (p *Provider) Region() (string, error) {
    method CompartmentOCID (line 70) | func (p *Provider) CompartmentOCID() (string, error) {
    method GetNetworkClient (line 74) | func (p *Provider) GetNetworkClient() (
    method GetComputeClient (line 96) | func (p *Provider) GetComputeClient() (
  function NewProvider (line 118) | func NewProvider(authPv AuthProvider) (prov *Provider, err error) {

FILE: oracle/routetable.go
  type RouteTable (line 11) | type RouteTable struct
    method RouteExists (line 18) | func (r *RouteTable) RouteExists(dest string, nextHopId string) bool {
    method RouteUpsert (line 25) | func (r *RouteTable) RouteUpsert(dest string, nextHopId string) bool {
    method CommitRouteRules (line 50) | func (r *RouteTable) CommitRouteRules(pv *Provider) (err error) {
  function GetRouteTables (line 74) | func GetRouteTables(pv *Provider, vcnId string) (

FILE: oracle/subnet.go
  type Vcn (line 12) | type Vcn struct
  type Subnet (line 19) | type Subnet struct
  function GetSubnet (line 26) | func GetSubnet(pv *Provider, subnetId string) (subnet *Subnet, err error) {
  function GetVcns (line 61) | func GetVcns(pv *Provider) (vcns []*Vcn, err error) {
  function GetSubnets (line 114) | func GetSubnets(pv *Provider, vcnId string) (subnets []*Subnet, err erro...

FILE: oracle/utils.go
  function loadPrivateKey (line 15) | func loadPrivateKey(mdata *Metadata) (

FILE: oracle/vnic.go
  type Vnic (line 14) | type Vnic struct
    method SetSkipSourceDestCheck (line 26) | func (v *Vnic) SetSkipSourceDestCheck(pv *Provider, val bool) (err err...
  function GetVnic (line 50) | func GetVnic(pv *Provider, vnicId string) (vnic *Vnic, err error) {
  function getVnicAttachment (line 131) | func getVnicAttachment(pv *Provider, attachmentId string) (
  function CreateVnic (line 158) | func CreateVnic(pv *Provider, name, subnetId string,
  function RemoveVnic (line 243) | func RemoveVnic(pv *Provider, vnicAttachId string) (err error) {

FILE: organization/organization.go
  type Organization (line 12) | type Organization struct
    method Validate (line 19) | func (d *Organization) Validate(db *database.Database) (
    method Commit (line 31) | func (d *Organization) Commit(db *database.Database) (err error) {
    method CommitFields (line 42) | func (d *Organization) CommitFields(db *database.Database, fields set....
    method Insert (line 55) | func (c *Organization) Insert(db *database.Database) (err error) {

FILE: organization/utils.go
  function Get (line 10) | func Get(db *database.Database, dcId bson.ObjectID) (
  function GetAll (line 24) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllName (line 62) | func GetAllName(db *database.Database) (orgs []*Organization, err error) {
  function GetAllNameRoles (line 99) | func GetAllNameRoles(db *database.Database, roles []string) (
  function GetAllPaged (line 141) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 205) | func Remove(db *database.Database, dcId bson.ObjectID) (err error) {
  function Count (line 224) | func Count(db *database.Database) (count int64, err error) {

FILE: paths/paths.go
  function GetVmUuid (line 16) | func GetVmUuid(instId bson.ObjectID) string {
  function GetVmPath (line 37) | func GetVmPath(instId bson.ObjectID) string {
  function GetDisksPath (line 42) | func GetDisksPath() string {
  function GetLocalIsosPath (line 46) | func GetLocalIsosPath() string {
  function GetBackingPath (line 50) | func GetBackingPath() string {
  function GetTpmsPath (line 54) | func GetTpmsPath() string {
  function GetTpmPath (line 58) | func GetTpmPath(virtId bson.ObjectID) string {
  function GetTpmSockPath (line 62) | func GetTpmSockPath(virtId bson.ObjectID) string {
  function GetTpmPwdPath (line 66) | func GetTpmPwdPath(virtId bson.ObjectID) string {
  function GetTempPath (line 70) | func GetTempPath() string {
  function GetTempDir (line 74) | func GetTempDir() string {
  function GetDrivePath (line 78) | func GetDrivePath(driveId string) string {
  function GetCachesDir (line 82) | func GetCachesDir() string {
  function GetCacheDir (line 86) | func GetCacheDir(virtId bson.ObjectID) string {
  function GetOvmfDir (line 90) | func GetOvmfDir() string {
  function GetDiskPath (line 94) | func GetDiskPath(diskId bson.ObjectID) string {
  function GetOvmfVarsPath (line 99) | func GetOvmfVarsPath(virtId bson.ObjectID) string {
  function GetDiskTempPath (line 104) | func GetDiskTempPath() string {
  function GetImageTempPath (line 109) | func GetImageTempPath() string {
  function GetImdsPath (line 114) | func GetImdsPath() string {
  function GetImdsConfPath (line 118) | func GetImdsConfPath(instId bson.ObjectID) string {
  function GetInstRunPath (line 123) | func GetInstRunPath(instId bson.ObjectID) string {
  function GetImdsSockPath (line 127) | func GetImdsSockPath(instId bson.ObjectID) string {
  function GetDiskMountPath (line 131) | func GetDiskMountPath() string {
  function GetInitsPath (line 135) | func GetInitsPath() string {
  function GetInitPath (line 139) | func GetInitPath(instId bson.ObjectID) string {
  function GetUnitName (line 144) | func GetUnitName(virtId bson.ObjectID) string {
  function GetUnitPath (line 148) | func GetUnitPath(virtId bson.ObjectID) string {
  function GetUnitNameDhcp4 (line 152) | func GetUnitNameDhcp4(virtId bson.ObjectID, n int) string {
  function GetUnitPathDhcp4 (line 156) | func GetUnitPathDhcp4(virtId bson.ObjectID, n int) string {
  function GetUnitNameDhcp6 (line 160) | func GetUnitNameDhcp6(virtId bson.ObjectID, n int) string {
  function GetUnitPathDhcp6 (line 164) | func GetUnitPathDhcp6(virtId bson.ObjectID, n int) string {
  function GetUnitNameNdp (line 168) | func GetUnitNameNdp(virtId bson.ObjectID, n int) string {
  function GetUnitPathNdp (line 172) | func GetUnitPathNdp(virtId bson.ObjectID, n int) string {
  function GetUnitNameTpm (line 177) | func GetUnitNameTpm(virtId bson.ObjectID) string {
  function GetUnitPathTpm (line 181) | func GetUnitPathTpm(virtId bson.ObjectID) string {
  function GetUnitNameImds (line 186) | func GetUnitNameImds(virtId bson.ObjectID) string {
  function GetUnitNameDhcpc (line 190) | func GetUnitNameDhcpc(virtId bson.ObjectID) string {
  function GetShareId (line 194) | func GetShareId(virtId bson.ObjectID, shareName string) string {
  function GetUnitNameShare (line 202) | func GetUnitNameShare(virtId bson.ObjectID, shareId string) string {
  function GetUnitNameShares (line 206) | func GetUnitNameShares(virtId bson.ObjectID) string {
  function GetUnitPathImds (line 210) | func GetUnitPathImds(virtId bson.ObjectID) string {
  function GetUnitPathDhcpc (line 215) | func GetUnitPathDhcpc(virtId bson.ObjectID) string {
  function GetUnitPathShare (line 220) | func GetUnitPathShare(virtId bson.ObjectID, shareId string) string {
  function GetUnitPathShares (line 225) | func GetUnitPathShares(virtId bson.ObjectID) string {
  function GetPidPath (line 230) | func GetPidPath(virtId bson.ObjectID) string {
  function GetShareSockPath (line 235) | func GetShareSockPath(virtId bson.ObjectID, shareId string) string {
  function GetHugepagePath (line 240) | func GetHugepagePath(virtId bson.ObjectID) string {
  function GetSockPath (line 244) | func GetSockPath(virtId bson.ObjectID) string {
  function GetQmpSockPath (line 249) | func GetQmpSockPath(virtId bson.ObjectID) string {
  function GetGuestPath (line 254) | func GetGuestPath(virtId bson.ObjectID) string {
  function GetPidPathOld (line 260) | func GetPidPathOld(virtId bson.ObjectID) string {
  function GetSockPathOld (line 266) | func GetSockPathOld(virtId bson.ObjectID) string {
  function GetQmpSockPathOld (line 272) | func GetQmpSockPathOld(virtId bson.ObjectID) string {
  function GetGuestPathOld (line 278) | func GetGuestPathOld(virtId bson.ObjectID) string {
  function GetNamespacesPath (line 283) | func GetNamespacesPath() string {
  function GetNamespacePath (line 287) | func GetNamespacePath(namespace string) string {

FILE: paths/utils.go
  function existsFile (line 34) | func existsFile(pth string) (exists bool, err error) {
  function FindOvmfCodePath (line 52) | func FindOvmfCodePath(secureBoot bool) (pth string, err error) {
  function FindOvmfVarsPath (line 96) | func FindOvmfVarsPath(secureBoot bool) (pth string, err error) {

FILE: pci/pci.go
  type Device (line 14) | type Device struct

FILE: pci/utils.go
  function CheckSlot (line 16) | func CheckSlot(slot string) bool {
  function GetVfio (line 20) | func GetVfio(slot string) (dev *Device, err error) {
  function GetVfioAll (line 36) | func GetVfioAll() (devices []*Device, err error) {

FILE: permission/permission.go
  function chown (line 15) | func chown(virt *vm.VirtualMachine, path string) (err error) {
  function touchChown (line 30) | func touchChown(virt *vm.VirtualMachine, path string) (err error) {
  function mkdirChown (line 46) | func mkdirChown(virt *vm.VirtualMachine, path string) (err error) {
  function Restore (line 62) | func Restore(pth string) (err error) {
  function Chown (line 76) | func Chown(virt *vm.VirtualMachine, pth string) (err error) {
  function InitVirt (line 85) | func InitVirt(virt *vm.VirtualMachine) (err error) {
  function InitDisk (line 144) | func InitDisk(virt *vm.VirtualMachine, dsk *vm.Disk) (err error) {
  function InitTpm (line 158) | func InitTpm(virt *vm.VirtualMachine) (err error) {
  function InitTpmPwd (line 169) | func InitTpmPwd(virt *vm.VirtualMachine) (err error) {
  function InitImds (line 180) | func InitImds(virt *vm.VirtualMachine) (err error) {
  function InitMount (line 191) | func InitMount(virt *vm.VirtualMachine, shareId string) (err error) {

FILE: permission/user.go
  function GetUserName (line 16) | func GetUserName(vmId bson.ObjectID) string {
  function UserAdd (line 20) | func UserAdd(virt *vm.VirtualMachine) (err error) {
  function UserDelete (line 52) | func UserDelete(virt *vm.VirtualMachine) (err error) {
  function UserGroupAdd (line 68) | func UserGroupAdd(virtId bson.ObjectID, group string) (err error) {
  function UserGroupDelete (line 83) | func UserGroupDelete(virtId bson.ObjectID, group string) (err error) {

FILE: plan/constants.go
  constant Start (line 8) | Start   = "start"
  constant Stop (line 9) | Stop    = "stop"
  constant Restart (line 10) | Restart = "restart"
  constant Destroy (line 11) | Destroy = "destroy"

FILE: plan/data.go
  type Data (line 11) | type Data struct
    method Export (line 31) | func (d *Data) Export() (data eval.Data, err error) {
  type Unit (line 16) | type Unit struct
  type Instance (line 21) | type Instance struct
  function GetEmtpyData (line 53) | func GetEmtpyData() (data eval.Data, err error) {

FILE: plan/plan.go
  type Plan (line 13) | type Plan struct
    method Validate (line 32) | func (p *Plan) Validate(db *database.Database) (
    method UpdateStatements (line 73) | func (p *Plan) UpdateStatements(inStatements []*Statement) (err error) {
    method Commit (line 106) | func (p *Plan) Commit(db *database.Database) (err error) {
    method CommitFields (line 117) | func (p *Plan) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 130) | func (p *Plan) Insert(db *database.Database) (err error) {
  type Completion (line 21) | type Completion struct
  type Statement (line 27) | type Statement struct

FILE: plan/utils.go
  function Get (line 10) | func Get(db *database.Database, plnId bson.ObjectID) (
  function GetOrg (line 24) | func GetOrg(db *database.Database, orgId, plnId bson.ObjectID) (
  function ExistsOrg (line 42) | func ExistsOrg(db *database.Database, orgId, plnId bson.ObjectID) (
  function GetOne (line 63) | func GetOne(db *database.Database, query *bson.M) (pln *Plan, err error) {
  function GetAll (line 76) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllPaged (line 109) | func GetAllPaged(db *database.Database, query *bson.M,
  function GetAllName (line 169) | func GetAllName(db *database.Database, query *bson.M) (
  function Remove (line 210) | func Remove(db *database.Database, plnId bson.ObjectID) (err error) {
  function RemoveOrg (line 229) | func RemoveOrg(db *database.Database, orgId, plnId bson.ObjectID) (
  function RemoveMulti (line 251) | func RemoveMulti(db *database.Database, plnIds []bson.ObjectID) (err err...
  function RemoveMultiOrg (line 267) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: planner/planner.go
  type Planner (line 24) | type Planner struct
    method setInstanceAction (line 28) | func (p *Planner) setInstanceAction(db *database.Database,
    method checkInstance (line 84) | func (p *Planner) checkInstance(db *database.Database,
    method ApplyPlans (line 291) | func (p *Planner) ApplyPlans(db *database.Database) (err error) {

FILE: planner/utils.go
  function buildEvalData (line 13) | func buildEvalData(unt *unit.Unit,

FILE: pod/pod.go
  type Pod (line 16) | type Pod struct
    method Validate (line 41) | func (p *Pod) Validate(db *database.Database) (
    method Json (line 61) | func (p *Pod) Json(usrId bson.ObjectID) {
    method InitUnits (line 69) | func (p *Pod) InitUnits(db *database.Database, units []*unit.UnitInput) (
    method CommitFieldsUnits (line 133) | func (p *Pod) CommitFieldsUnits(db *database.Database,
    method Commit (line 316) | func (p *Pod) Commit(db *database.Database) (err error) {
    method CommitFields (line 327) | func (p *Pod) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 340) | func (p *Pod) Insert(db *database.Database) (err error) {
  type Completion (line 26) | type Completion struct
  type UnitDraft (line 32) | type UnitDraft struct

FILE: pod/utils.go
  function Get (line 14) | func Get(db *database.Database, podId bson.ObjectID) (
  function GetOrg (line 28) | func GetOrg(db *database.Database, orgId, pdId bson.ObjectID) (
  function GetOne (line 46) | func GetOne(db *database.Database, query *bson.M) (pd *Pod, err error) {
  function GetAll (line 59) | func GetAll(db *database.Database, query *bson.M) (
  function GetAllPaged (line 92) | func GetAllPaged(db *database.Database, query *bson.M,
  function UpdateDrafts (line 156) | func UpdateDrafts(db *database.Database, podId, usrId bson.ObjectID,
  function UpdateDraftsOrg (line 179) | func UpdateDraftsOrg(db *database.Database, orgId, podId, usrId bson.Obj...
  function Remove (line 203) | func Remove(db *database.Database, podId bson.ObjectID) (err error) {
  function RemoveOrg (line 237) | func RemoveOrg(db *database.Database, orgId, podId bson.ObjectID) (
  function RemoveMulti (line 276) | func RemoveMulti(db *database.Database, podIds []bson.ObjectID) (
  function RemoveMultiOrg (line 313) | func RemoveMultiOrg(db *database.Database, orgId bson.ObjectID,

FILE: policy/constants.go
  constant Optional (line 4) | Optional          = "optional"
  constant Required (line 5) | Required          = "required"
  constant Disabled (line 6) | Disabled          = "disabled"
  constant OperatingSystem (line 7) | OperatingSystem   = "operating_system"
  constant Browser (line 8) | Browser           = "browser"
  constant Location (line 9) | Location          = "location"
  constant WhitelistNetworks (line 10) | WhitelistNetworks = "whitelist_networks"
  constant BlacklistNetworks (line 11) | BlacklistNetworks = "blacklist_networks"

FILE: policy/policy.go
  type Rule (line 22) | type Rule struct
  type Policy (line 28) | type Policy struct
    method Validate (line 41) | func (p *Policy) Validate(db *database.Database) (
    method ValidateUser (line 118) | func (p *Policy) ValidateUser(db *database.Database, usr *user.User,
    method Commit (line 323) | func (p *Policy) Commit(db *database.Database) (err error) {
    method CommitFields (line 334) | func (p *Policy) CommitFields(db *database.Database, fields set.Set) (
    method Insert (line 347) | func (p *Policy) Insert(db *database.Database) (err error) {

FILE: policy/utils.go
  function Get (line 10) | func Get(db *database.Database, policyId bson.ObjectID) (
  function GetService (line 24) | func GetService(db *database.Database, podId bson.ObjectID) (
  function GetRoles (line 62) | func GetRoles(db *database.Database, roles []string) (
  function GetAll (line 106) | func GetAll(db *database.Database) (policies []*Policy, err error) {
  function GetAllPaged (line 140) | func GetAllPaged(db *database.Database, query *bson.M,
  function Remove (line 204) | func Remove(db *database.Database, policyId bson.ObjectID) (err error) {
  function RemoveMulti (line 218) | func RemoveMulti(db *database.Database, polcyIds []bson.ObjectID) (

FILE: pool/constants.go
  constant Lvm (line 4) | Lvm = "lvm"
  constant Active (line 6) | Active = "active"

FILE: pool/pool.go
  type Pool (line 11) | type Pool struct
    method Json (line 28) | func (p *Pool) Json(nodeNames map[bson.ObjectID]string) {
    method Validate (line 31) | func (p *Pool) Validate(db *database.Database) (
    method Commit (line 55) | func (p *Pool) Commit(db *database.Database) (err error) {
    method C
Condensed preview — 1089 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8,534K chars).
[
  {
    "path": ".gitattributes",
    "chars": 114,
    "preview": "www/app/EditorThemes.ts linguist-vendored\n*.html linguist-vendored\n*.css linguist-vendored\n*.js linguist-vendored\n"
  },
  {
    "path": ".gitignore",
    "chars": 182,
    "preview": ".DS_Store\n.DS_Store?\n._*\n.Spotlight-V100\n.Trashes\nIcon?\nehthumbs.db\nThumbs.db\n*.pyc\n*.egg\n*.egg-info\nbuild_keys.json\n/pr"
  },
  {
    "path": "CHANGES",
    "chars": 10917,
    "preview": "pritunl-cloud changelog\n=======================\n\n<%= version %>\n\nAdd Google Cloud DNS support\nAdd support to manual rene"
  },
  {
    "path": "LICENSE",
    "chars": 9121,
    "preview": "Copyright (c) 2013-2026 Pritunl\n\n                               LICENSE SUMMARY\n\n* License does not expire\n* Can be used"
  },
  {
    "path": "README.md",
    "chars": 3604,
    "preview": "# pritunl-cloud: declarative kvm virtualization\n\n[![github](https://img.shields.io/badge/github-pritunl-181717.svg?style"
  },
  {
    "path": "acme/acme.go",
    "chars": 9764,
    "preview": "package acme\n\nimport (\n\t\"context\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n"
  },
  {
    "path": "acme/challenge.go",
    "chars": 1086,
    "preview": "package acme\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/databas"
  },
  {
    "path": "acme/constants.go",
    "chars": 138,
    "preview": "package acme\n\nconst (\n\tAcmeDirectory = \"https://acme-v02.api.letsencrypt.org/directory\"\n\tAcmePath      = \"/.well-known/a"
  },
  {
    "path": "acme/utils.go",
    "chars": 3518,
    "preview": "package acme\n\nimport (\n\t\"context\"\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"crypto/rsa\"\n\t\"crypto/x509\"\n\t\"crypt"
  },
  {
    "path": "advisory/advisory.go",
    "chars": 4979,
    "preview": "package advisory\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo"
  },
  {
    "path": "advisory/constants.go",
    "chars": 1275,
    "preview": "package advisory\n\nimport (\n\t\"regexp\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n)\n\nconst (\n\tNone      = \"none\"\n\tLow "
  },
  {
    "path": "advisory/utils.go",
    "chars": 6645,
    "preview": "package advisory\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"git"
  },
  {
    "path": "agent/agent.go",
    "chars": 10136,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropb"
  },
  {
    "path": "agent/constants/constants.go",
    "chars": 144,
    "preview": "package constants\n\nconst (\n\tVersion      = \"1.0.3248.95\"\n\tImdsConfPath = \"/etc/pritunl-imds.json\"\n\tImdsLogPath  = \"/var/"
  },
  {
    "path": "agent/imds/imds.go",
    "chars": 8676,
    "preview": "package imds\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"run"
  },
  {
    "path": "agent/imds/journal.go",
    "chars": 1069,
    "preview": "package imds\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/agent/logging\"\n\t\"github.com/pritunl/tools/logger\"\n)\n\ntype Jour"
  },
  {
    "path": "agent/imds/sync.go",
    "chars": 1303,
    "preview": "package imds\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/imds/types\"\n\t\"github.com/pritunl/pritunl-clou"
  },
  {
    "path": "agent/imds/utils.go",
    "chars": 1060,
    "preview": "package imds\n\nimport (\n\t\"encoding/json\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/pritunl-cloud/agent"
  },
  {
    "path": "agent/logging/file.go",
    "chars": 3180,
    "preview": "package logging\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"os/exec\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godro"
  },
  {
    "path": "agent/logging/handler.go",
    "chars": 182,
    "preview": "package logging\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/imds/types\"\n)\n\ntype Handler interface {\n\tOpen() (err error)"
  },
  {
    "path": "agent/logging/logging.go",
    "chars": 2569,
    "preview": "package logging\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritu"
  },
  {
    "path": "agent/logging/systemd.go",
    "chars": 4327,
    "preview": "package logging\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"os/exec\"\n\t\"runtime/debug\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\""
  },
  {
    "path": "agent/utils/sanitize.go",
    "chars": 3058,
    "preview": "package utils\n\nimport (\n\t\"strings\"\n\n\t\"github.com/pritunl/pritunl-cloud/agent/constants\"\n\t\"github.com/pritunl/tools/comma"
  },
  {
    "path": "agent/utils/sys.go",
    "chars": 472,
    "preview": "package utils\n\nimport (\n\t\"io/ioutil\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/pritunl-"
  },
  {
    "path": "aggregate/block.go",
    "chars": 3770,
    "preview": "package aggregate\n\nimport (\n\t\"sync\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go-driver/"
  },
  {
    "path": "aggregate/deployment.go",
    "chars": 8047,
    "preview": "package aggregate\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/da"
  },
  {
    "path": "aggregate/disk.go",
    "chars": 3455,
    "preview": "package aggregate\n\nimport (\n\t\"sync\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson"
  },
  {
    "path": "aggregate/domain.go",
    "chars": 3100,
    "preview": "package aggregate\n\nimport (\n\t\"sync\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson"
  },
  {
    "path": "aggregate/instance.go",
    "chars": 9772,
    "preview": "package aggregate\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.co"
  },
  {
    "path": "aggregate/pod.go",
    "chars": 4375,
    "preview": "package aggregate\n\nimport (\n\t\"sort\"\n\t\"sync\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver"
  },
  {
    "path": "aggregate/shape.go",
    "chars": 3361,
    "preview": "package aggregate\n\nimport (\n\t\"sync\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson"
  },
  {
    "path": "ahandlers/alert.go",
    "chars": 6538,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/audit.go",
    "chars": 1006,
    "preview": "package ahandlers\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/audit\"\n\t\"github.c"
  },
  {
    "path": "ahandlers/auth.go",
    "chars": 18321,
    "preview": "package ahandlers\n\nimport (\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/"
  },
  {
    "path": "ahandlers/authority.go",
    "chars": 6596,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/balancer.go",
    "chars": 6388,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/block.go",
    "chars": 5953,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/certificate.go",
    "chars": 7117,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/check.go",
    "chars": 114,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n)\n\nfunc checkGet(c *gin.Context) {\n\tc.String(200, \"ok\")\n}\n"
  },
  {
    "path": "ahandlers/completion.go",
    "chars": 5239,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritu"
  },
  {
    "path": "ahandlers/csrf.go",
    "chars": 1060,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/authorizer\"\n\t\"github.com/prit"
  },
  {
    "path": "ahandlers/datacenter.go",
    "chars": 7122,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/devices.go",
    "chars": 6878,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"githu"
  },
  {
    "path": "ahandlers/disk.go",
    "chars": 10534,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/domain.go",
    "chars": 5496,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/event.go",
    "chars": 3239,
    "preview": "package ahandlers\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/gin-gonic/gin"
  },
  {
    "path": "ahandlers/firewall.go",
    "chars": 6157,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/handlers.go",
    "chars": 10311,
    "preview": "package ahandlers\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/config\"\n\t\"github"
  },
  {
    "path": "ahandlers/image.go",
    "chars": 5038,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/instance.go",
    "chars": 17779,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set"
  },
  {
    "path": "ahandlers/license.go",
    "chars": 923,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritu"
  },
  {
    "path": "ahandlers/log.go",
    "chars": 1657,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/mon"
  },
  {
    "path": "ahandlers/node.go",
    "chars": 18399,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/contai"
  },
  {
    "path": "ahandlers/organization.go",
    "chars": 4940,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/plan.go",
    "chars": 4920,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/pod.go",
    "chars": 18088,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/policy.go",
    "chars": 6616,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/pool.go",
    "chars": 5935,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pritunl/pritunl-cloud/node\"\n\t\"github.co"
  },
  {
    "path": "ahandlers/relations.go",
    "chars": 1120,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/database\"\n\t\"github.com/pritun"
  },
  {
    "path": "ahandlers/secret.go",
    "chars": 6200,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/session.go",
    "chars": 1191,
    "preview": "package ahandlers\n\nimport (\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/database\""
  },
  {
    "path": "ahandlers/settings.go",
    "chars": 5301,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritu"
  },
  {
    "path": "ahandlers/shape.go",
    "chars": 6840,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/static.go",
    "chars": 2984,
    "preview": "package ahandlers\n\nimport (\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/auth\"\n\t\"github.co"
  },
  {
    "path": "ahandlers/storage.go",
    "chars": 6449,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/subscription.go",
    "chars": 1956,
    "preview": "package ahandlers\n\nimport (\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/gin-gonic/gin\"\n\t\"gith"
  },
  {
    "path": "ahandlers/theme.go",
    "chars": 1000,
    "preview": "package ahandlers\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritu"
  },
  {
    "path": "ahandlers/user.go",
    "chars": 7122,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set"
  },
  {
    "path": "ahandlers/vpc.go",
    "chars": 7511,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "ahandlers/zone.go",
    "chars": 5348,
    "preview": "package ahandlers\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"gith"
  },
  {
    "path": "alert/alert.go",
    "chars": 2635,
    "preview": "package alert\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"gi"
  },
  {
    "path": "alert/constants.go",
    "chars": 111,
    "preview": "package alert\n\nconst (\n\tLow    = 1\n\tMedium = 5\n\tHigh   = 10\n)\n\nconst (\n\tInstanceOffline = \"instance_offline\"\n)\n"
  },
  {
    "path": "alert/utils.go",
    "chars": 5284,
    "preview": "package alert\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"gi"
  },
  {
    "path": "alertevent/alertevent.go",
    "chars": 4069,
    "preview": "package alertevent\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-"
  },
  {
    "path": "alertevent/utils.go",
    "chars": 2649,
    "preview": "package alertevent\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/"
  },
  {
    "path": "arp/arp.go",
    "chars": 3668,
    "preview": "package arp\n\nimport (\n\t\"encoding/json\"\n\t\"net\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/godrop"
  },
  {
    "path": "audit/audit.go",
    "chars": 948,
    "preview": "package audit\n\nimport (\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\""
  },
  {
    "path": "audit/constants.go",
    "chars": 1840,
    "preview": "package audit\n\nconst (\n\tAdminLogin                 = \"admin_login\"\n\tAdminLoginFailed           = \"admin_login_failed\"\n\tA"
  },
  {
    "path": "audit/utils.go",
    "chars": 1926,
    "preview": "package audit\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go"
  },
  {
    "path": "auth/auth.go",
    "chars": 823,
    "preview": "package auth\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-c"
  },
  {
    "path": "auth/authzero.go",
    "chars": 10941,
    "preview": "package auth\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/e"
  },
  {
    "path": "auth/azure.go",
    "chars": 8459,
    "preview": "package auth\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/"
  },
  {
    "path": "auth/constants.go",
    "chars": 57,
    "preview": "package auth\n\nconst (\n\tAdmin = \"admin\"\n\tUser  = \"user\"\n)\n"
  },
  {
    "path": "auth/errortypes.go",
    "chars": 115,
    "preview": "package auth\n\nimport (\n\t\"github.com/dropbox/godropbox/errors\"\n)\n\ntype InvalidState struct {\n\terrors.DropboxError\n}\n"
  },
  {
    "path": "auth/google.go",
    "chars": 3938,
    "preview": "package auth\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n"
  },
  {
    "path": "auth/handler.go",
    "chars": 8706,
    "preview": "package auth\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha512\"\n\t\"crypto/subtle\"\n\t\"encoding/base64\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"gith"
  },
  {
    "path": "auth/jumpcloud.go",
    "chars": 4156,
    "preview": "package auth\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.c"
  },
  {
    "path": "auth/saml.go",
    "chars": 2312,
    "preview": "package auth\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors"
  },
  {
    "path": "auth/state.go",
    "chars": 2478,
    "preview": "package auth\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\n\t\"github.com/pritunl/pritunl-cloud/settings\"\n)\n\ntype StateProvider struct {\n\tId  "
  },
  {
    "path": "auth/sync.go",
    "chars": 1200,
    "preview": "package auth\n\nimport (\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/pritunl-cloud/databas"
  },
  {
    "path": "auth/utils.go",
    "chars": 2131,
    "preview": "package auth\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/pritunl/pritunl-cloud/cookie\"\n\t\"github.com/pritunl/pr"
  },
  {
    "path": "authority/authority.go",
    "chars": 2020,
    "preview": "package authority\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"githu"
  },
  {
    "path": "authority/constants.go",
    "chars": 182,
    "preview": "package authority\n\nimport \"github.com/pritunl/mongo-go-driver/v2/bson\"\n\nconst (\n\tSshKey         = \"ssh_key\"\n\tSshCertific"
  },
  {
    "path": "authority/utils.go",
    "chars": 7164,
    "preview": "package authority\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go-driver/v2/mongo/"
  },
  {
    "path": "authorizer/authorizer.go",
    "chars": 2266,
    "preview": "package authorizer\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/pritunl/pritunl-cloud/cookie\"\n\t\"github.com/pritunl/pritunl-cloud/"
  },
  {
    "path": "authorizer/constants.go",
    "chars": 63,
    "preview": "package authorizer\n\nconst (\n\tAdmin = \"admin\"\n\tUser  = \"user\"\n)\n"
  },
  {
    "path": "authorizer/utils.go",
    "chars": 1833,
    "preview": "package authorizer\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/pritunl/pritunl-cloud/auth\"\n\t\"github.com/pritunl/pritunl-cloud/da"
  },
  {
    "path": "backup/backup.go",
    "chars": 6512,
    "preview": "package backup\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/"
  },
  {
    "path": "balancer/balancer.go",
    "chars": 7723,
    "preview": "package balancer\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/god"
  },
  {
    "path": "balancer/constants.go",
    "chars": 43,
    "preview": "package balancer\n\nconst (\n\tHttp = \"http\"\n)\n"
  },
  {
    "path": "balancer/utils.go",
    "chars": 3673,
    "preview": "package balancer\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go-driver/v2/mongo/o"
  },
  {
    "path": "block/block.go",
    "chars": 14756,
    "preview": "package block\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t"
  },
  {
    "path": "block/constants.go",
    "chars": 129,
    "preview": "package block\n\nconst (\n\tExternal = \"external\"\n\tHost     = \"host\"\n\tNodePort = \"node_port\"\n\tIPv4     = \"ipv4\"\n\tIPv6     = "
  },
  {
    "path": "block/errortypes.go",
    "chars": 113,
    "preview": "package block\n\nimport (\n\t\"github.com/dropbox/godropbox/errors\"\n)\n\ntype BlockFull struct {\n\terrors.DropboxError\n}\n"
  },
  {
    "path": "block/ip.go",
    "chars": 421,
    "preview": "package block\n\nimport (\n\t\"net\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n"
  },
  {
    "path": "block/utils.go",
    "chars": 7527,
    "preview": "package block\n\nimport (\n\t\"net\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"g"
  },
  {
    "path": "bridges/bridges.go",
    "chars": 2756,
    "preview": "package bridges\n\nimport (\n\t\"io/ioutil\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dr"
  },
  {
    "path": "certificate/certificate.go",
    "chars": 6082,
    "preview": "package certificate\n\nimport (\n\t\"crypto/md5\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com"
  },
  {
    "path": "certificate/constants.go",
    "chars": 366,
    "preview": "package certificate\n\nimport \"github.com/pritunl/mongo-go-driver/v2/bson\"\n\nconst (\n\tText        = \"text\"\n\tLetsEncrypt = \""
  },
  {
    "path": "certificate/utils.go",
    "chars": 5024,
    "preview": "package certificate\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go-driver/v2/mong"
  },
  {
    "path": "cloud/cloud.go",
    "chars": 421,
    "preview": "package cloud\n\ntype Subnet struct {\n\tId      string `bson:\"id\" json:\"id\"`\n\tVpcId   string `bson:\"vpc_id\" json:\"vpc_id\"`\n"
  },
  {
    "path": "cloud/oracle.go",
    "chars": 926,
    "preview": "package cloud\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/oracle\"\n)\n\nvar (\n\tlastOracleSync time.Time\n\toracleVp"
  },
  {
    "path": "cloudinit/cloudinit.go",
    "chars": 19332,
    "preview": "package cloudinit\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"mime/multipart\"\n\t\"net\"\n\t\"net/textproto"
  },
  {
    "path": "cloudinit/query.go",
    "chars": 1736,
    "preview": "package cloudinit\n\nimport (\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/pritun"
  },
  {
    "path": "cloudinit/utils.go",
    "chars": 1126,
    "preview": "package cloudinit\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"text/template\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"githu"
  },
  {
    "path": "cmd/backup.go",
    "chars": 482,
    "preview": "package cmd\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/pritunl-cloud/ba"
  },
  {
    "path": "cmd/dhcp.go",
    "chars": 1784,
    "preview": "package cmd\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pri"
  },
  {
    "path": "cmd/imds.go",
    "chars": 166,
    "preview": "package cmd\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/imds/server\"\n)\n\nfunc ImdsServer() (err error) {\n\terr = server.M"
  },
  {
    "path": "cmd/instance.go",
    "chars": 1197,
    "preview": "package cmd\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"gith"
  },
  {
    "path": "cmd/log.go",
    "chars": 320,
    "preview": "package cmd\n\nimport (\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/pritunl/pritunl-cloud/database\"\n\t\"github.com/pritunl/pr"
  },
  {
    "path": "cmd/mtu.go",
    "chars": 176,
    "preview": "package cmd\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/mtu\"\n)\n\nfunc MtuCheck() (err error) {\n\tchk := mtu.NewCheck()\n\n\t"
  },
  {
    "path": "cmd/node.go",
    "chars": 1919,
    "preview": "package cmd\n\nimport (\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl"
  },
  {
    "path": "cmd/optimize.go",
    "chars": 922,
    "preview": "package cmd\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n\t\"github.com/sirupsen/logrus\"\n)\n\nfunc Optimize() (err er"
  },
  {
    "path": "cmd/settings.go",
    "chars": 4259,
    "preview": "package cmd\n\nimport (\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo"
  },
  {
    "path": "colorize/colorize.go",
    "chars": 848,
    "preview": "package colorize\n\ntype Color string\n\nconst (\n\tNone       = \"\"\n\tBold       = \"\\033[1m\"\n\tBlack      = \"\\033[0;30m\"\n\tBlackB"
  },
  {
    "path": "completion/completion.go",
    "chars": 15785,
    "preview": "package completion\n\nimport (\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl"
  },
  {
    "path": "compositor/compositor.go",
    "chars": 3757,
    "preview": "package compositor\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os/user\"\n\t\"path\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbo"
  },
  {
    "path": "config/config.go",
    "chars": 3767,
    "preview": "package config\n\nimport (\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/g"
  },
  {
    "path": "constants/constants.go",
    "chars": 3303,
    "preview": "package constants\n\nimport (\n\t\"time\"\n)\n\nconst (\n\tVersion         = \"2.0.3665.99\"\n\tDatabaseVersion = 1\n\tLogPath         = "
  },
  {
    "path": "cookie/cookie.go",
    "chars": 4503,
    "preview": "package cookie\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/godropbox/error"
  },
  {
    "path": "cookie/utils.go",
    "chars": 1733,
    "preview": "package cookie\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/gorilla/securecookie\"\n\t\"github"
  },
  {
    "path": "crypto/crypto.go",
    "chars": 7152,
    "preview": "package crypto\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/rand\"\n\t\"crypto/sha512\"\n\t\"crypto/subtle\"\n\t\"encoding/base64\"\n\t\"encoding/j"
  },
  {
    "path": "csrf/csrf.go",
    "chars": 923,
    "preview": "package csrf\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/database\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)"
  },
  {
    "path": "data/disk.go",
    "chars": 2554,
    "preview": "package data\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/pritunl-cloud/database\"\n\t\"git"
  },
  {
    "path": "data/image.go",
    "chars": 40931,
    "preview": "package data\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n"
  },
  {
    "path": "data/resize.go",
    "chars": 3939,
    "preview": "package data\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/pritunl-clou"
  },
  {
    "path": "data/sync.go",
    "chars": 5882,
    "preview": "package data\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/go"
  },
  {
    "path": "data/utils.go",
    "chars": 577,
    "preview": "package data\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/base32\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\""
  },
  {
    "path": "database/base.go",
    "chars": 197,
    "preview": "package database\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n)\n\ntype Named struct {\n\tId   bson.ObjectID `bso"
  },
  {
    "path": "database/client.go",
    "chars": 857,
    "preview": "package database\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/mongo\"\n\t\"g"
  },
  {
    "path": "database/collection.go",
    "chars": 7228,
    "preview": "package database\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/prit"
  },
  {
    "path": "database/database.go",
    "chars": 23036,
    "preview": "package database\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driv"
  },
  {
    "path": "database/errors.go",
    "chars": 493,
    "preview": "package database\n\nimport (\n\t\"github.com/dropbox/godropbox/errors\"\n)\n\ntype ConnectionError struct {\n\terrors.DropboxError\n"
  },
  {
    "path": "database/index.go",
    "chars": 4012,
    "preview": "package database\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"g"
  },
  {
    "path": "database/utils.go",
    "chars": 2944,
    "preview": "package database\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-drive"
  },
  {
    "path": "datacenter/constants.go",
    "chars": 141,
    "preview": "package datacenter\n\nconst (\n\tDefault     = \"default\"\n\tVxlanVlan   = \"vxlan_vlan\"\n\tWgVxlanVlan = \"wg_vxlan_vlan\"\n\n\tWg4 = "
  },
  {
    "path": "datacenter/datacenter.go",
    "chars": 5485,
    "preview": "package datacenter\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"gith"
  },
  {
    "path": "datacenter/utils.go",
    "chars": 5438,
    "preview": "package datacenter\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go-driver/v2/mongo"
  },
  {
    "path": "defaults/defaults.go",
    "chars": 16332,
    "preview": "package defaults\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"net\"\n\t\"slices\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github."
  },
  {
    "path": "demo/alert.go",
    "chars": 433,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/alert\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar Alerts"
  },
  {
    "path": "demo/authority.go",
    "chars": 1921,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/authority\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar Au"
  },
  {
    "path": "demo/balancer.go",
    "chars": 1341,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/balance"
  },
  {
    "path": "demo/block.go",
    "chars": 1069,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/aggregate\"\n\t\"github.com/pritunl/pritunl-cloud/block\"\n\t\"github."
  },
  {
    "path": "demo/certificate.go",
    "chars": 2701,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/certifi"
  },
  {
    "path": "demo/datacenter.go",
    "chars": 700,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/datacenter\"\n\t\"gi"
  },
  {
    "path": "demo/demo.go",
    "chars": 529,
    "preview": "package demo\n\nimport (\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/pritunl/pritunl-cloud/errortypes\"\n\t\"github.com/pritunl/p"
  },
  {
    "path": "demo/disk.go",
    "chars": 13310,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/aggregate\"\n\t\"github.com/pritunl/pritunl-cloud/disk\"\n\t"
  },
  {
    "path": "demo/domain.go",
    "chars": 3321,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/domain\""
  },
  {
    "path": "demo/firewall.go",
    "chars": 806,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/firewall\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar Fir"
  },
  {
    "path": "demo/instance.go",
    "chars": 32536,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/instance\"\n\t\"github.com/pritunl/pritunl-cloud/telemetr"
  },
  {
    "path": "demo/log.go",
    "chars": 767,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/log\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar"
  },
  {
    "path": "demo/node.go",
    "chars": 25474,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/cloud\"\n"
  },
  {
    "path": "demo/organization.go",
    "chars": 304,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/organization\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar"
  },
  {
    "path": "demo/plan.go",
    "chars": 665,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/plan\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar Plans ="
  },
  {
    "path": "demo/pod.go",
    "chars": 39280,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/aggrega"
  },
  {
    "path": "demo/policy.go",
    "chars": 778,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/policy\"\n\t\"github"
  },
  {
    "path": "demo/pool.go",
    "chars": 488,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/pool\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar Pools ="
  },
  {
    "path": "demo/rand.go",
    "chars": 1171,
    "preview": "package demo\n\nimport (\n\t\"sync\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n"
  },
  {
    "path": "demo/secret.go",
    "chars": 968,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/secret\"\n\t\"github"
  },
  {
    "path": "demo/shape.go",
    "chars": 1457,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/shape\"\n\t\"github."
  },
  {
    "path": "demo/storage.go",
    "chars": 714,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/storage\"\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n)\n\nvar Stor"
  },
  {
    "path": "demo/subscription.go",
    "chars": 424,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/subscription\"\n)\n\nvar Subscription = &subscription.Sub"
  },
  {
    "path": "demo/user.go",
    "chars": 2067,
    "preview": "package demo\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/audit\"\n"
  },
  {
    "path": "demo/vpc.go",
    "chars": 3290,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n\t\"github.com/pritunl/pritunl-cloud/vpc\"\n)\n\nvar Vpcs = ["
  },
  {
    "path": "demo/zone.go",
    "chars": 370,
    "preview": "package demo\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/utils\"\n\t\"github.com/pritunl/pritunl-cloud/zone\"\n)\n\nvar Zones ="
  },
  {
    "path": "deploy/deploy.go",
    "chars": 1655,
    "preview": "package deploy\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/pritunl-cloud/database\"\n\t\"github.com/pritunl/pritunl-cloud/state\""
  },
  {
    "path": "deploy/deployments.go",
    "chars": 28465,
    "preview": "package deploy\n\nimport (\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/mongo-go"
  },
  {
    "path": "deploy/disks.go",
    "chars": 12163,
    "preview": "package deploy\n\nimport (\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/dropbox/godropbox/errors\"\n\t"
  },
  {
    "path": "deploy/imds.go",
    "chars": 4040,
    "preview": "package deploy\n\nimport (\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/pritunl-cloud/certificate\"\n\t"
  },
  {
    "path": "deploy/instances.go",
    "chars": 23664,
    "preview": "package deploy\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/d"
  },
  {
    "path": "deploy/ipset.go",
    "chars": 772,
    "preview": "package deploy\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/ipset\"\n\t\"github.com/pritunl/pritunl-cloud/state\"\n)\n\ntype Ips"
  },
  {
    "path": "deploy/iptables.go",
    "chars": 637,
    "preview": "package deploy\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/iptables\"\n\t\"github.com/pritunl/pritunl-cloud/state\"\n)\n\ntype "
  },
  {
    "path": "deploy/namespace.go",
    "chars": 2556,
    "preview": "package deploy\n\nimport (\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/pritunl-"
  },
  {
    "path": "deploy/network.go",
    "chars": 4447,
    "preview": "package deploy\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/pritunl/pritunl-cloud/block\"\n\t\"github.com/pritunl/pritunl-cloud/bridges\"\n\t"
  },
  {
    "path": "deploy/services.go",
    "chars": 10953,
    "preview": "package deploy\n\nimport (\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/pritunl-cloud/datab"
  },
  {
    "path": "deployment/constants.go",
    "chars": 748,
    "preview": "package deployment\n\nimport (\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n)\n\nconst (\n\tProvision = \"provision\"\n"
  },
  {
    "path": "deployment/deployment.go",
    "chars": 7938,
    "preview": "package deployment\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/mongo-go"
  },
  {
    "path": "deployment/utils.go",
    "chars": 6791,
    "preview": "package deployment\n\nimport (\n\t\"github.com/dropbox/godropbox/container/set\"\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\""
  },
  {
    "path": "device/constants.go",
    "chars": 204,
    "preview": "package device\n\nconst (\n\tU2f       = \"u2f\"\n\tWebAuthn  = \"webauthn\"\n\tSecondary = \"secondary\"\n\tPhone     = \"phone\"\n\tCall  "
  },
  {
    "path": "device/device.go",
    "chars": 5650,
    "preview": "package device\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/x509\"\n\t\"time\"\n\n\t\"github.com/dropbox/godropbox/conta"
  },
  {
    "path": "device/facet.go",
    "chars": 557,
    "preview": "package device\n\nimport (\n\t\"github.com/pritunl/pritunl-cloud/settings\"\n)\n\ntype FacetVersion struct {\n\tMajor int `json:\"ma"
  },
  {
    "path": "device/utils.go",
    "chars": 3976,
    "preview": "package device\n\nimport (\n\t\"time\"\n\n\t\"github.com/pritunl/mongo-go-driver/v2/bson\"\n\t\"github.com/pritunl/mongo-go-driver/v2/"
  },
  {
    "path": "dhcpc/constants.go",
    "chars": 162,
    "preview": "package dhcpc\n\nimport (\n\t\"time\"\n)\n\nconst (\n\tMaxMessageSize  = 1500\n\tDefaultInterval = 60 * time.Second\n\tDhcpTimeout     "
  },
  {
    "path": "dhcpc/dhcpc.go",
    "chars": 8317,
    "preview": "package dhcpc\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pritunl/tools/lo"
  },
  {
    "path": "dhcpc/imds.go",
    "chars": 2171,
    "preview": "package dhcpc\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com"
  },
  {
    "path": "dhcpc/lease.go",
    "chars": 1232,
    "preview": "package dhcpc\n\nimport (\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/insomniacslk/dhcp/dhcpv6\"\n)\n\ntype Lease struct {\n\tIface            "
  },
  {
    "path": "dhcpc/lease4.go",
    "chars": 2856,
    "preview": "package dhcpc\n\nimport (\n\t\"context\"\n\t\"net\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/insomniacslk/dhcp/dhcpv4\""
  },
  {
    "path": "dhcpc/lease6.go",
    "chars": 6324,
    "preview": "package dhcpc\n\nimport (\n\t\"context\"\n\t\"net\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/insomniacslk/dhcp/dhcpv6\""
  },
  {
    "path": "dhcpc/systemd.go",
    "chars": 3988,
    "preview": "package dhcpc\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/pritunl/mongo-go-driver/v"
  },
  {
    "path": "dhcpc/utils.go",
    "chars": 2899,
    "preview": "package dhcpc\n\nimport (\n\t\"encoding/hex\"\n\t\"net\"\n\n\t\"github.com/dropbox/godropbox/errors\"\n\t\"github.com/insomniacslk/dhcp/dh"
  }
]

// ... and 889 more files (download for full content)

About this extraction

This page contains the full source code of the pritunl/pritunl-cloud GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1089 files (7.3 MB), approximately 2.0M tokens, and a symbol index with 6772 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!