Set custom global variables in Caddyfile - caddy

I have multiple reverse_proxy entries that share the same destination host. Isn't there a way to set a global variable inside the Caddyfile in order to reuse it?
app1.dns {
reverse_proxy myhost:xxxx
}
app2.dns {
reverse_proxy myhost:yyyy
}
app3.dns {
reverse_proxy myhost:zzzz
}

Caddy Snippets
The re-usable global configuration is possible to define once use anywhere within caddyfile, example here
(snippet) {
respond "Yahaha! You found {args.0}!"
}
(hello) {
respond "Hello {args.0}!"
}
a.example.com {
import snippet "Example A"
}
b.example.com {
import hello "World"
}

Related

using bash or variables within Chef Inspec

Im new to Chef /Inspec test writing.
What Im trying to do is validate a host name/IP address within a file and match it to what is in DNS. If the IP address in file doesnt match what is in DNS, the test should fail.
example
describe host('example.com') do
it { should be_resolvable }
its('ipaddress') { should include '12.34.56.78' }
its('stdout') { should match 'ipaddress' }
end
the 'example.com' would be a $variable that comes from within a file
the ''12.34.56.78' would also be a $variable that comes from within a file however should match what is in DNS
Is this even possible to do? do I need to or can I use a bash script within the inspec file that has some awk commands?
describe bash('filename.sh') do
it { should be_resolvable }
its('stdout') { should match 'ipaddress' }
its('stderr') { should eq '' }
its('ipaddress') { should include '12.34.56.78' }
end
Any help or guidance is much appreciated. Thank you!!

Puppet - Set defined types in Nodes.pp

How to overwrite defined type in nodes.pp? I want to able to set custom domain using nodes.pp. Case Default isn't an option.
I'm using puppet 6.0..
The following method doesn't work. It says Could not find declared class resolv::resolv_config.
It looks like it used to work in 3.0 according to this answer.
nodes.pp
node "test001" {
class { 'resolv::resolv_config':
domain => "something.local",
}
}
modules/resolv/manifests/init.pp
class resolv {
case $hostname {
/^[Abc][Xyz]/: {
resolv:resolv_config { 'US':
domain => "mydomain.local",
}
}
}
}
define resolv::resolv_config($domain){
file { '/etc/resolv.conf':
content => template("resolv/resolv.conf.erb"),
}
}
resolv.conf.erb
domain <%= #domain %>
There are a couple of problems here, but the one causing the "could not find declared class" error is that you are using the wrong syntax for declaring a defined type. Your code should be something like this:
node "test001" {
resolv::resolv_config { 'something.local':
domain => "something.local",
}
}
There are examples of declaring defined types in the documentation, https://puppet.com/docs/puppet/latest/lang_defined_types.html.
Once you get that working, you'll find another problem, in that this definition
define resolv::resolv_config($domain){
file { '/etc/resolv.conf':
content => template("resolv/resolv.conf.erb"),
}
}
will cause a error if you try to declare more than one resolv::resolv_config, because they will both try to declare the /etc/resolv.conf file resource. You almost certainly wanted to use a file_line resource.

How to properly design API module in TypeScript?

I want to design a TypeScript (2.7) module for accessing external IS, let's call it InfoSys. I used the following approach.
I created info-sys.ts which defines a API class and related interfaces and enums, like:
class Api {
constructor(private endpoint: Endpoint) {
// ...
}
}
enum Endpoint {
CONTACTS = "contacts"
}
interface Contact {
name: string;
}
Now I want to export all the stuff under specific name. So I appended the export statement:
export const InfoSys = {
Api,
Endpoint,
Contact
};
When I try to use the module in another file, like:
import { InfoSys } from "info-sys";
// this line throws error: "Cannot find namespace 'InfoSys'"
private api: InfoSys.Api;
// but this line is ok
api = new InfoSys.Api(InfoSys.Endpoint.CONTACTS);
The way that works is the following - to export every piece individually:
export class Api {
constructor(private endpoint: Endpoint) {
// ...
}
}
export enum Endpoint {
CONTACTS = "contacts"
}
export interface Contact {
name: string;
}
and import them all to a single variable:
import * as InfoSys from "info-sys";
But the name of the variable can be whatever. It is not critical for functionality but I want to force developers, who will use the info-sys module, to use a specific name while accessing it (for easier readability and maintainability). How to properly design such module?
You can use namespace:
export namespace InfoSys {
Api,
Endpoint,
Contact
};
In general, this approach should be avoided. But in your case, it is fine as you are delivering things that are tightly related.
If Api is the single entry point to all these, I would also recommend this:
export class InfoSysApi { ... }
export namespace InfoSysApi {
export enum Endpoint = { ... }
export interface Contact { ... }
}
UPDATE:
To make sure I get the point through, DON'T do the following:
export namespace Foo {
export function X() { return 'x' }
export function Y() { return 'y' }
}
Only use export namespace to export "tugged in types", not values.
In TypeScript handbook: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
Although the table says namespace can contain values, it is considered bad practice if you are writing ESM (import/export).
Namespace and ESM are two different mechanisms to achieve similar result.
Don't mix them together.

Puppet roles/profiles, role with multiple instances of profile - how do parameters work?

I am just learning Puppet (we have Puppet Enterprise locally). I am trying to understand the "roles and profiles" pattern. Please pardon any nomenclature slip ups.
How do I create a role with multiple instances of a profile, where the profile instances differ only by parameter? I'm guessing Hiera fits into this somewhere but I'm not exactly sure how.
For example:
Puppetfile:
mod 'puppetlabs-apache', '2.3.0'
apache.pp profile
class profile::apache (
String $port = '80',
) {
class { 'apache':
listen => $port,
}
}
twoapaches.pp role
class role::twoapaches {
include profile::apache
include profile::apache
}
I want an instance of the twoapaches role to have an apache at ports 90 and 100 - how do I do that?
You actually can't use classes like that in Puppet; a class can only be declared once-per-node.
You probably need some of the defined types in the puppetlabs/apache module. Defined types are used when you need to declare a user-defined "resource" more than once on a single node.
E.g. profile might be:
class profile::two_vhosts {
apache::vhost { 'ip1.example.com':
ip => ['127.0.0.1','169.254.1.1'],
port => '80',
docroot => '/var/www/ip',
}
apache::vhost { 'ip2.example.com':
ip => ['127.0.0.1'],
port => '8080',
docroot => '/var/www/ip',
}
}
And the role might be:
class role::two_vhosts {
include profile::two_vhosts
include profile::other_stuff
...
}
If you needed to then pass the ports in, you might have:
class profile::two_vhosts (
String $ip1_port,
String $ip2_port,
) {
apache::vhost { 'ip1.example.com':
ip => ['127.0.0.1','169.254.1.1'],
port => $ip1_port,
docroot => '/var/www/ip',
}
apache::vhost { 'ip2.example.com':
ip => ['127.0.0.1'],
port => $ip2_port,
docroot => '/var/www/ip',
}
}
You could then have your role as:
class role::two_vhosts {
class { 'profile::two_vhosts':
ip1_port => '80',
ip2_port => '8080',
}
include profile::other_stuff
...
}
But in practice people use the Automatic Parameter Lookup feature here in conjunction with Hiera (ref).
I would use Hiera also for the parameters. This way you can easily change ports if needed and you comply with the rule of no putting classes inside the roles:
class role::two_vhosts {
include profile::two_vhosts
include profile::other_stuff
...
}
Hiera configuration when including the role would be something like this:
profile::two_vhosts::ip1_port: '80'
profile::two_vhosts::ip2_port: '8080'

manage hosts file on Windows using Puppet

I'm trying to manage my hosts file on a Windows machine using Puppet and Hiera. My problem is that I have never really used Hiera and I'm struggling with parsing the data content into a proper format.
The relevant section in hieradata/hiera.yaml looks like this:
myhosts : [
'host1 1.2.3.4',
'host2 2.3.4.5',
'host3 3.4.5.6']
I have code that uses a host module, but it also depends on a class that I don't have, so naturally it doesn't work.
class hosts::module (
$myhosts = hiera('myhosts'),
)
{
define update_hosts {
$value = split($name,' ')
host {
"${value[0]}" : ip => "${value[1]}",
}
}
update_hosts { $myhosts :; }
}
I have tried using the file resource instead of the host resource, and also tried doing it without any class, but for some reason I am getting this error
Error: Could not retrieve catalog from remote server: Error 500 on SERVER:
Server Error: Evaluation Error: Error while evaluating a Resource Statement,
Evaluation Error: Error while evaluating a Resource Statement, Duplicate
declaration: File[C:\Temp\tmp.txt] is already declared in file
/etc/puppetlabs/code/environments/production/manifests/site.pp:4; cannot redeclare
at /etc/puppetlabs/code/environments/production/manifests/site.pp:4
at /etc/puppetlabs/code/environments/production/manifests/site.pp:4:1
at /etc/puppetlabs/code/environments/production/manifests/site.pp:10 on node puppet-agent
As you can see, it claims that I have a duplicate declaration, but the weird thing is that it says it has a problem with the same line. It thinks it's declaring the same thing twice for some reason.
This is the code I have now (I know it won't work but the error doesn't really sound related)
define hosts_update($content) {
file { 'C:\Temp\tmp.txt' :
ensure => file,
content => $content,
}
}
hosts_update{ hiera('myhosts'):
content => split($name," "),
}
Any idea how to do this right?
fixed it.
site.pp
include update_hosts
init.pp
class update_hosts::host
(
$hosts = hiera('hosts_list'),
)
{
update_host { $hosts :; }
}
host.pp
define update_host {
​
$value = split($name,' ')
​
host {
"${value[0]}" : ip => "${value[1]}",
target => "C:/Windows/System32/drivers/etc/hosts"
}
}

Resources