describe firewalld do
  it { should be_installed }
  it { should be_running }
  its('default_zone') { should eq 'home' }
  it { should have_zone('ztest') }
end

describe firewalld.where(zone: 'ztest') do
  its('interfaces') { should cmp [%w(eth1337 eth2337)] }
  its('sources') { should cmp [['192.0.2.2']] }
  its('services') { should cmp [['ssh']] }
end

# Why does it give me undefined method `target' for Firewall Rules with zone == "ztest"?
# describe firewalld.where (zone: 'ztest') do
#   its('target') { should cmp 'asdf' }
#   its('ports') { should cmp 'asdf' }
#   its('protocols') { should cmp 'asdf' }
#   its('forward_ports') { should cmp 'asdf' }
#   its('source_ports') { should cmp 'asdf' }
#   its('icmp_blocks') { should cmp 'asdf' }
#   its('rich_rules') { should cmp 'asdf' }
#   it { should have_icmp_block_inversion_enabled }
#   it { should have_masquerade_enabled }
# end

describe command('firewall-cmd --info-helper=example-helper') do
  example_helper = <<~EOF
    example-helper
      family: ipv6
      module: nf_conntrack_irc
      ports: 6667/tcp 5556/udp
  EOF
  its(:stdout) { should cmp example_helper }
end

describe command('firewall-cmd --info-helper=minimal-helper') do
  minimal_helper = <<~EOF
    minimal-helper
      family: ipv4
      module: nf_conntrack_netbios_ns
      ports: 7778/udp
  EOF
  its(:stdout) { should cmp minimal_helper }
end

describe command('firewall-cmd --permanent --helper=minimal-helper --get-description') do
  its(:stdout) { should cmp "Generated by chef from firewalld-test[default] by firewalld_helper[minimal-helper]\n" }
end

describe command('firewall-cmd --permanent --icmptype=rick-rolled --get-destinations') do
  # Tag is missing if ipv4 and ipv6 are set
  its(:stdout) { should cmp "ipv4\n" }
end

describe command('firewall-cmd --permanent --icmptype=minimal-icmptype --get-destinations') do
  its(:stdout) { should cmp "ipv4\nipv6\n" }
end

describe command('firewall-cmd --info-ipset=example-ips') do
  example_ips_config = <<~EOF
    example-ips
      type: hash:ip
      options: family=inet hashsize=1000 maxelem=255
      entries: 192.0.2.16 192.0.2.32
  EOF
  its(:stdout) { should cmp example_ips_config }
end

describe command('firewall-cmd --info-ipset=single-ip') do
  single_ip_config = <<~EOF
    single-ip
      type: hash:ip
      options:#{' '}
      entries: 192.0.2.22
  EOF
  its(:stdout) { should cmp single_ip_config }
end

describe command('firewall-cmd --info-policy=ptest') do
  ptest_config = <<~EOF
    ptest (active)
      priority: 10
      target: ACCEPT
      ingress-zones: home
      egress-zones: dmz
      services: ssh
      ports: 23/udp
      protocols: udp
      masquerade: no
      forward-ports:#{' '}
    \tport=8081:proto=tcp:toport=81:toaddr=192.0.2.1
    \tport=8084-8085:proto=tcp:toport=84-85:toaddr=192.0.2.5
      source-ports: 23/udp
      icmp-blocks:#{' '}
      rich rules:#{' '}
    \trule family="ipv4" source address="192.168.0.14" accept
  EOF
  its(:stdout) { should cmp ptest_config }
end

describe command('firewall-cmd --info-policy=pminimal') do
  pminimal = <<~EOF
    pminimal (active)
      priority: -1
      target: CONTINUE
      ingress-zones: internal
      egress-zones: external
      services:#{' '}
      ports:#{' '}
      protocols:#{' '}
      masquerade: no
      forward-ports:#{' '}
      source-ports:#{' '}
      icmp-blocks:#{' '}
      rich rules:#{' '}
    EOF
  its(:stdout) { should cmp pminimal }
end

describe command('firewall-cmd --info-service=ssh2') do
  ssh2_config = <<~EOF
    ssh2
      ports: 2222/tcp
      protocols: udp
      source-ports: 23/tcp
      modules:#{' '}
      destination: ipv4:192.0.2.0 ipv6:::1
      includes: ssh
      helpers: tftp
  EOF

  its(:stdout) { should cmp ssh2_config }
end

describe command('firewall-cmd --info-service=minimal-service') do
  ssh2_config = <<~EOF
    minimal-service
      ports: 1/udp
      protocols:#{' '}
      source-ports:#{' '}
      modules:#{' '}
      destination:#{' '}
      includes:#{' '}
      helpers:#{' '}
  EOF

  its(:stdout) { should cmp ssh2_config }
end

describe command('firewall-cmd --info-zone=home') do
  ptest_config = <<~EOF
    home (active)
      target: default
      icmp-block-inversion: yes
      interfaces: eth0
      sources:#{' '}
      services: dhcpv6-client mdns samba-client ssh
      ports:#{' '}
      protocols:#{' '}
      forward: no
      masquerade: no
      forward-ports:#{' '}
      source-ports:#{' '}
      icmp-blocks:#{' '}
      rich rules:#{' '}
  EOF
  its(:stdout) { should cmp ptest_config }
end

describe command('firewall-cmd --info-zone=ztest') do
  ptest_config = <<~EOF
    ztest (active)
      target: ACCEPT
      icmp-block-inversion: yes
      interfaces: eth1337 eth2337
      sources: 192.0.2.2
      services: ssh
      ports: 23/udp
      protocols: udp
      forward: yes
      masquerade: yes
      forward-ports:#{' '}
    \tport=8080:proto=tcp:toport=80:toaddr=192.0.2.1
      source-ports: 23/udp
      icmp-blocks: echo-reply echo-request network-unreachable
      rich rules:#{' '}
    \trule family="ipv4" source address="192.168.0.14" accept
  EOF
  its(:stdout) { should cmp ptest_config }
end

describe command('firewall-cmd --info-zone=ztest2') do
  ptest_config = <<~EOF
    ztest2 (active)
      target: default
      icmp-block-inversion: no
      interfaces:#{' '}
      sources: 192.0.2.0/24
      services:#{' '}
      ports:#{' '}
      protocols:#{' '}
      forward: no
      masquerade: no
      forward-ports:#{' '}
      source-ports:#{' '}
      icmp-blocks:#{' '}
      rich rules:#{' '}
  EOF
  its(:stdout) { should cmp ptest_config }
end

describe service('firewalld') do
  it { should be_installed }
  it { should be_enabled }
  it { should be_running }
end
