Repository: aws-cloudformation/cfn-lint

Issue:
ValueError: list.remove(x): x not in list
### CloudFormation Lint Version

0.76.0

### What operating system are you using?

macOS

### Describe the bug

We run latest `cfn-lint` on all templates in the [AWS SAM repository](https://github.com/aws/serverless-application-model/); looks like 0.76.0 introduced a bug.

Since today, `cfn-lint` fails with:

```text
Traceback (most recent call last):
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/bin/cfn-lint", line 8, in <module>
    sys.exit(main())
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/__main__.py", line 39, in main
    matches = list(cfnlint.core.get_matches(filenames, args))
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/core.py", line 173, in get_matches
    matches = run_cli(
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/core.py", line 78, in run_cli
    return run_checks(filename, template, rules, regions, mandatory_rules)
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/core.py", line 334, in run_checks
    runner = cfnlint.runner.Runner(
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/runner.py", line 32, in __init__
    self.cfn = Template(filename, template, regions)
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/template/template.py", line 44, in __init__
    self.conditions = cfnlint.conditions.Conditions(self)
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/conditions/conditions.py", line 34, in __init__
    self._cnf, self._solver_params = self._build_cnf(list(self._conditions.keys()))
  File "/Users/rehnc/Desktop/tmp/serverless-application-model/.venv_cfn_lint/lib/python3.10/site-packages/cfnlint/conditions/conditions.py", line 118, in _build_cnf
    allowed_values[param.hash].remove(get_hash(equal_1.left))
ValueError: list.remove(x): x not in list
```

### Expected behavior

Expected it not to fail, or to fail like a template violation would.

### Reproduction template

Not sure yet which one is causing the issue, but this reproduces it:

```bash
git clone https://github.com/aws/serverless-application-model.git --depth 1
cd serverless-application-model
python3 -m venv .venv
.venv/bin/python -m pip install cfn-lint==0.76.0
.venv/bin/cfn-lint
```

However, if you try with `.venv/bin/python -m pip install cfn-lint==0.75.0`, it succeeds.


Discussion:
Working on the issue but also found a use case for a new rule.
This is one of those scenarios of an always False case.

```
"Conditions": {
    "CreateProdResources": {
      "Fn::Equals": [
        {
          "Ref": "InstanceTypeParameter"
        },
        "prod"
      ]
    }
  },
...
"Parameters": {
    "InstanceTypeParameter": {
      "AllowedValues": [
        "t2.micro",
        "m1.small",
        "m1.large"
      ],
```

Resolving patch:
diff --git a/src/cfnlint/conditions/conditions.py b/src/cfnlint/conditions/conditions.py
--- a/src/cfnlint/conditions/conditions.py
+++ b/src/cfnlint/conditions/conditions.py
@@ -115,9 +115,15 @@ def _build_cnf(
                     if param.hash not in allowed_values:
                         continue
                     if isinstance(equal_1.left, str):
-                        allowed_values[param.hash].remove(get_hash(equal_1.left))
+                        if get_hash(equal_1.left) in allowed_values[param.hash]:
+                            allowed_values[param.hash].remove(get_hash(equal_1.left))
+                        else:
+                            equal_vars[equal_1.hash] = BooleanFalse()
                     if isinstance(equal_1.right, str):
-                        allowed_values[param.hash].remove(get_hash(equal_1.right))
+                        if get_hash(equal_1.right) in allowed_values[param.hash]:
+                            allowed_values[param.hash].remove(get_hash(equal_1.right))
+                        else:
+                            equal_vars[equal_1.hash] = BooleanFalse()
 
             # iteration 2 builds the cnf formulas to make sure any empty lists
             # are now full not equals
@@ -157,10 +163,10 @@ def build_scenarios(self, condition_names: List[str]) -> Iterator[Dict[str, bool
             return
 
         # if only one condition we will assume its True/False
-        if len(condition_names) == 1:
-            yield {condition_names[0]: True}
-            yield {condition_names[0]: False}
-            return
+        # if len(condition_names) == 1:
+        #    yield {condition_names[0]: True}
+        #    yield {condition_names[0]: False}
+        #    return
 
         try:
             # build a large matric of True/False options based on the provided conditions


Test patch:
diff --git a/test/unit/module/conditions/test_conditions.py b/test/unit/module/conditions/test_conditions.py
--- a/test/unit/module/conditions/test_conditions.py
+++ b/test/unit/module/conditions/test_conditions.py
@@ -127,7 +127,7 @@ def test_check_never_false(self):
             ],
         )
 
-    def test_check_can_be_salfe(self):
+    def test_check_can_be_false(self):
         """With allowed values two conditions can both be false"""
         template = decode_str(
             """
@@ -151,3 +151,32 @@ def test_check_can_be_salfe(self):
                 {"IsProd": False, "IsDev": False},
             ],
         )
+
+    def test_check_can_be_good_when_condition_value(self):
+        """Some times a condition Equals doesn't match to allowed values"""
+        template = decode_str(
+            """
+        Parameters:
+          Environment:
+            Type: String
+            AllowedValues: ["prod", "dev", "stage"]
+        Conditions:
+          IsGamma: !Equals [!Ref Environment, "gamma"]
+          IsBeta: !Equals ["beta", !Ref Environment]
+        """
+        )[0]
+
+        cfn = Template("", template)
+        self.assertEqual(len(cfn.conditions._conditions), 2)
+        self.assertListEqual(
+            list(cfn.conditions.build_scenarios(["IsGamma", "IsBeta"])),
+            [
+                {"IsBeta": False, "IsGamma": False},
+            ],
+        )
+        self.assertListEqual(
+            list(cfn.conditions.build_scenarios(["IsGamma"])),
+            [
+                {"IsGamma": False},
+            ],
+        )